Merge branch 'upstream-fixes' into upstream
authorJeff Garzik <jeff@garzik.org>
Wed, 24 May 2006 05:49:12 +0000 (01:49 -0400)
committerJeff Garzik <jeff@garzik.org>
Wed, 24 May 2006 05:49:12 +0000 (01:49 -0400)
Conflicts:

drivers/scsi/libata-core.c

31 files changed:
drivers/ide/pci/amd74xx.c
drivers/scsi/Makefile
drivers/scsi/ahci.c
drivers/scsi/ata_piix.c
drivers/scsi/libata-bmdma.c
drivers/scsi/libata-core.c
drivers/scsi/libata-eh.c [new file with mode: 0644]
drivers/scsi/libata-scsi.c
drivers/scsi/libata.h
drivers/scsi/pdc_adma.c
drivers/scsi/sata_mv.c
drivers/scsi/sata_nv.c
drivers/scsi/sata_promise.c
drivers/scsi/sata_qstor.c
drivers/scsi/sata_sil.c
drivers/scsi/sata_sil24.c
drivers/scsi/sata_sis.c
drivers/scsi/sata_svw.c
drivers/scsi/sata_sx4.c
drivers/scsi/sata_uli.c
drivers/scsi/sata_via.c
drivers/scsi/sata_vsc.c
drivers/scsi/scsi.c
drivers/scsi/scsi_error.c
drivers/scsi/scsi_lib.c
drivers/scsi/scsi_transport_api.h [new file with mode: 0644]
include/linux/ata.h
include/linux/libata.h
include/linux/pci_ids.h
include/scsi/scsi_cmnd.h
include/scsi/scsi_host.h

index b22ee54..6e9dbf4 100644 (file)
@@ -74,6 +74,7 @@ static struct amd_ide_chip {
        { PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_IDE,        0x50, AMD_UDMA_133 },
        { PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_IDE,        0x50, AMD_UDMA_133 },
        { PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_IDE,        0x50, AMD_UDMA_133 },
+       { PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_IDE,        0x50, AMD_UDMA_133 },
        { PCI_DEVICE_ID_AMD_CS5536_IDE,                 0x40, AMD_UDMA_100 },
        { 0 }
 };
@@ -488,7 +489,8 @@ static ide_pci_device_t amd74xx_chipsets[] __devinitdata = {
        /* 14 */ DECLARE_NV_DEV("NFORCE-MCP04"),
        /* 15 */ DECLARE_NV_DEV("NFORCE-MCP51"),
        /* 16 */ DECLARE_NV_DEV("NFORCE-MCP55"),
-       /* 17 */ DECLARE_AMD_DEV("AMD5536"),
+       /* 17 */ DECLARE_NV_DEV("NFORCE-MCP61"),
+       /* 18 */ DECLARE_AMD_DEV("AMD5536"),
 };
 
 static int __devinit amd74xx_probe(struct pci_dev *dev, const struct pci_device_id *id)
@@ -525,7 +527,8 @@ static struct pci_device_id amd74xx_pci_tbl[] = {
        { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_IDE,  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 14 },
        { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_IDE,  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 15 },
        { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_IDE,  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 16 },
-       { PCI_VENDOR_ID_AMD,    PCI_DEVICE_ID_AMD_CS5536_IDE,           PCI_ANY_ID, PCI_ANY_ID, 0, 0, 17 },
+       { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_IDE,  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 17 },
+       { PCI_VENDOR_ID_AMD,    PCI_DEVICE_ID_AMD_CS5536_IDE,           PCI_ANY_ID, PCI_ANY_ID, 0, 0, 18 },
        { 0, },
 };
 MODULE_DEVICE_TABLE(pci, amd74xx_pci_tbl);
index 81803a1..669ff6b 100644 (file)
@@ -164,7 +164,7 @@ ncr53c8xx-flags-$(CONFIG_SCSI_ZALON) \
 CFLAGS_ncr53c8xx.o     := $(ncr53c8xx-flags-y) $(ncr53c8xx-flags-m)
 zalon7xx-objs  := zalon.o ncr53c8xx.o
 NCR_Q720_mod-objs      := NCR_Q720.o ncr53c8xx.o
-libata-objs    := libata-core.o libata-scsi.o libata-bmdma.o
+libata-objs    := libata-core.o libata-scsi.o libata-bmdma.o libata-eh.o
 oktagon_esp_mod-objs   := oktagon_esp.o oktagon_io.o
 
 # Files generated that shall be removed upon make clean
index b4f8fb1..45fd71d 100644 (file)
@@ -48,7 +48,7 @@
 #include <asm/io.h>
 
 #define DRV_NAME       "ahci"
-#define DRV_VERSION    "1.2"
+#define DRV_VERSION    "1.3"
 
 
 enum {
@@ -56,12 +56,15 @@ enum {
        AHCI_MAX_SG             = 168, /* hardware max is 64K */
        AHCI_DMA_BOUNDARY       = 0xffffffff,
        AHCI_USE_CLUSTERING     = 0,
-       AHCI_CMD_SLOT_SZ        = 32 * 32,
+       AHCI_MAX_CMDS           = 32,
+       AHCI_CMD_SZ             = 32,
+       AHCI_CMD_SLOT_SZ        = AHCI_MAX_CMDS * AHCI_CMD_SZ,
        AHCI_RX_FIS_SZ          = 256,
-       AHCI_CMD_TBL_HDR        = 0x80,
        AHCI_CMD_TBL_CDB        = 0x40,
-       AHCI_CMD_TBL_SZ         = AHCI_CMD_TBL_HDR + (AHCI_MAX_SG * 16),
-       AHCI_PORT_PRIV_DMA_SZ   = AHCI_CMD_SLOT_SZ + AHCI_CMD_TBL_SZ +
+       AHCI_CMD_TBL_HDR_SZ     = 0x80,
+       AHCI_CMD_TBL_SZ         = AHCI_CMD_TBL_HDR_SZ + (AHCI_MAX_SG * 16),
+       AHCI_CMD_TBL_AR_SZ      = AHCI_CMD_TBL_SZ * AHCI_MAX_CMDS,
+       AHCI_PORT_PRIV_DMA_SZ   = AHCI_CMD_SLOT_SZ + AHCI_CMD_TBL_AR_SZ +
                                  AHCI_RX_FIS_SZ,
        AHCI_IRQ_ON_SG          = (1 << 31),
        AHCI_CMD_ATAPI          = (1 << 5),
@@ -71,8 +74,10 @@ enum {
        AHCI_CMD_CLR_BUSY       = (1 << 10),
 
        RX_FIS_D2H_REG          = 0x40, /* offset of D2H Register FIS data */
+       RX_FIS_UNK              = 0x60, /* offset of Unknown FIS data */
 
        board_ahci              = 0,
+       board_ahci_vt8251       = 1,
 
        /* global controller registers */
        HOST_CAP                = 0x00, /* host capabilities */
@@ -87,8 +92,9 @@ enum {
        HOST_AHCI_EN            = (1 << 31), /* AHCI enabled */
 
        /* HOST_CAP bits */
-       HOST_CAP_64             = (1 << 31), /* PCI DAC (64-bit DMA) support */
        HOST_CAP_CLO            = (1 << 24), /* Command List Override support */
+       HOST_CAP_NCQ            = (1 << 30), /* Native Command Queueing */
+       HOST_CAP_64             = (1 << 31), /* PCI DAC (64-bit DMA) support */
 
        /* registers for each SATA port */
        PORT_LST_ADDR           = 0x00, /* command list DMA addr */
@@ -127,15 +133,16 @@ enum {
        PORT_IRQ_PIOS_FIS       = (1 << 1), /* PIO Setup FIS rx'd */
        PORT_IRQ_D2H_REG_FIS    = (1 << 0), /* D2H Register FIS rx'd */
 
-       PORT_IRQ_FATAL          = PORT_IRQ_TF_ERR |
-                                 PORT_IRQ_HBUS_ERR |
-                                 PORT_IRQ_HBUS_DATA_ERR |
-                                 PORT_IRQ_IF_ERR,
-       DEF_PORT_IRQ            = PORT_IRQ_FATAL | PORT_IRQ_PHYRDY |
-                                 PORT_IRQ_CONNECT | PORT_IRQ_SG_DONE |
-                                 PORT_IRQ_UNK_FIS | PORT_IRQ_SDB_FIS |
-                                 PORT_IRQ_DMAS_FIS | PORT_IRQ_PIOS_FIS |
-                                 PORT_IRQ_D2H_REG_FIS,
+       PORT_IRQ_FREEZE         = PORT_IRQ_HBUS_ERR |
+                                 PORT_IRQ_IF_ERR |
+                                 PORT_IRQ_CONNECT |
+                                 PORT_IRQ_UNK_FIS,
+       PORT_IRQ_ERROR          = PORT_IRQ_FREEZE |
+                                 PORT_IRQ_TF_ERR |
+                                 PORT_IRQ_HBUS_DATA_ERR,
+       DEF_PORT_IRQ            = PORT_IRQ_ERROR | PORT_IRQ_SG_DONE |
+                                 PORT_IRQ_SDB_FIS | PORT_IRQ_DMAS_FIS |
+                                 PORT_IRQ_PIOS_FIS | PORT_IRQ_D2H_REG_FIS,
 
        /* PORT_CMD bits */
        PORT_CMD_ATAPI          = (1 << 24), /* Device is ATAPI */
@@ -153,6 +160,9 @@ enum {
 
        /* hpriv->flags bits */
        AHCI_FLAG_MSI           = (1 << 0),
+
+       /* ap->flags bits */
+       AHCI_FLAG_RESET_NEEDS_CLO       = (1 << 24),
 };
 
 struct ahci_cmd_hdr {
@@ -181,7 +191,6 @@ struct ahci_port_priv {
        dma_addr_t              cmd_slot_dma;
        void                    *cmd_tbl;
        dma_addr_t              cmd_tbl_dma;
-       struct ahci_sg          *cmd_tbl_sg;
        void                    *rx_fis;
        dma_addr_t              rx_fis_dma;
 };
@@ -193,13 +202,15 @@ static unsigned int ahci_qc_issue(struct ata_queued_cmd *qc);
 static irqreturn_t ahci_interrupt (int irq, void *dev_instance, struct pt_regs *regs);
 static int ahci_probe_reset(struct ata_port *ap, unsigned int *classes);
 static void ahci_irq_clear(struct ata_port *ap);
-static void ahci_eng_timeout(struct ata_port *ap);
 static int ahci_port_start(struct ata_port *ap);
 static void ahci_port_stop(struct ata_port *ap);
 static void ahci_tf_read(struct ata_port *ap, struct ata_taskfile *tf);
 static void ahci_qc_prep(struct ata_queued_cmd *qc);
 static u8 ahci_check_status(struct ata_port *ap);
-static inline int ahci_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc);
+static void ahci_freeze(struct ata_port *ap);
+static void ahci_thaw(struct ata_port *ap);
+static void ahci_error_handler(struct ata_port *ap);
+static void ahci_post_internal_cmd(struct ata_queued_cmd *qc);
 static void ahci_remove_one (struct pci_dev *pdev);
 
 static struct scsi_host_template ahci_sht = {
@@ -207,7 +218,8 @@ static struct scsi_host_template ahci_sht = {
        .name                   = DRV_NAME,
        .ioctl                  = ata_scsi_ioctl,
        .queuecommand           = ata_scsi_queuecmd,
-       .can_queue              = ATA_DEF_QUEUE,
+       .change_queue_depth     = ata_scsi_change_queue_depth,
+       .can_queue              = AHCI_MAX_CMDS - 1,
        .this_id                = ATA_SHT_THIS_ID,
        .sg_tablesize           = AHCI_MAX_SG,
        .cmd_per_lun            = ATA_SHT_CMD_PER_LUN,
@@ -233,14 +245,18 @@ static const struct ata_port_operations ahci_ops = {
        .qc_prep                = ahci_qc_prep,
        .qc_issue               = ahci_qc_issue,
 
-       .eng_timeout            = ahci_eng_timeout,
-
        .irq_handler            = ahci_interrupt,
        .irq_clear              = ahci_irq_clear,
 
        .scr_read               = ahci_scr_read,
        .scr_write              = ahci_scr_write,
 
+       .freeze                 = ahci_freeze,
+       .thaw                   = ahci_thaw,
+
+       .error_handler          = ahci_error_handler,
+       .post_internal_cmd      = ahci_post_internal_cmd,
+
        .port_start             = ahci_port_start,
        .port_stop              = ahci_port_stop,
 };
@@ -255,6 +271,16 @@ static const struct ata_port_info ahci_port_info[] = {
                .udma_mask      = 0x7f, /* udma0-6 ; FIXME */
                .port_ops       = &ahci_ops,
        },
+       /* board_ahci_vt8251 */
+       {
+               .sht            = &ahci_sht,
+               .host_flags     = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
+                                 ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA |
+                                 AHCI_FLAG_RESET_NEEDS_CLO,
+               .pio_mask       = 0x1f, /* pio0-4 */
+               .udma_mask      = 0x7f, /* udma0-6 ; FIXME */
+               .port_ops       = &ahci_ops,
+       },
 };
 
 static const struct pci_device_id ahci_pci_tbl[] = {
@@ -296,6 +322,8 @@ static const struct pci_device_id ahci_pci_tbl[] = {
          board_ahci }, /* ATI SB600 non-raid */
        { PCI_VENDOR_ID_ATI, 0x4381, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
          board_ahci }, /* ATI SB600 raid */
+       { PCI_VENDOR_ID_VIA, 0x3349, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+         board_ahci_vt8251 }, /* VIA VT8251 */
        { }     /* terminate list */
 };
 
@@ -374,8 +402,6 @@ static int ahci_port_start(struct ata_port *ap)
        pp->cmd_tbl = mem;
        pp->cmd_tbl_dma = mem_dma;
 
-       pp->cmd_tbl_sg = mem + AHCI_CMD_TBL_HDR;
-
        ap->private_data = pp;
 
        if (hpriv->cap & HOST_CAP_64)
@@ -508,46 +534,60 @@ static unsigned int ahci_dev_classify(struct ata_port *ap)
        return ata_dev_classify(&tf);
 }
 
-static void ahci_fill_cmd_slot(struct ahci_port_priv *pp, u32 opts)
+static void ahci_fill_cmd_slot(struct ahci_port_priv *pp, unsigned int tag,
+                              u32 opts)
 {
-       pp->cmd_slot[0].opts = cpu_to_le32(opts);
-       pp->cmd_slot[0].status = 0;
-       pp->cmd_slot[0].tbl_addr = cpu_to_le32(pp->cmd_tbl_dma & 0xffffffff);
-       pp->cmd_slot[0].tbl_addr_hi = cpu_to_le32((pp->cmd_tbl_dma >> 16) >> 16);
+       dma_addr_t cmd_tbl_dma;
+
+       cmd_tbl_dma = pp->cmd_tbl_dma + tag * AHCI_CMD_TBL_SZ;
+
+       pp->cmd_slot[tag].opts = cpu_to_le32(opts);
+       pp->cmd_slot[tag].status = 0;
+       pp->cmd_slot[tag].tbl_addr = cpu_to_le32(cmd_tbl_dma & 0xffffffff);
+       pp->cmd_slot[tag].tbl_addr_hi = cpu_to_le32((cmd_tbl_dma >> 16) >> 16);
 }
 
-static int ahci_poll_register(void __iomem *reg, u32 mask, u32 val,
-                             unsigned long interval_msec,
-                             unsigned long timeout_msec)
+static int ahci_clo(struct ata_port *ap)
 {
-       unsigned long timeout;
+       void __iomem *port_mmio = (void __iomem *) ap->ioaddr.cmd_addr;
+       struct ahci_host_priv *hpriv = ap->host_set->private_data;
        u32 tmp;
 
-       timeout = jiffies + (timeout_msec * HZ) / 1000;
-       do {
-               tmp = readl(reg);
-               if ((tmp & mask) == val)
-                       return 0;
-               msleep(interval_msec);
-       } while (time_before(jiffies, timeout));
+       if (!(hpriv->cap & HOST_CAP_CLO))
+               return -EOPNOTSUPP;
+
+       tmp = readl(port_mmio + PORT_CMD);
+       tmp |= PORT_CMD_CLO;
+       writel(tmp, port_mmio + PORT_CMD);
+
+       tmp = ata_wait_register(port_mmio + PORT_CMD,
+                               PORT_CMD_CLO, PORT_CMD_CLO, 1, 500);
+       if (tmp & PORT_CMD_CLO)
+               return -EIO;
 
-       return -1;
+       return 0;
 }
 
-static int ahci_softreset(struct ata_port *ap, int verbose, unsigned int *class)
+static int ahci_softreset(struct ata_port *ap, unsigned int *class)
 {
-       struct ahci_host_priv *hpriv = ap->host_set->private_data;
        struct ahci_port_priv *pp = ap->private_data;
        void __iomem *mmio = ap->host_set->mmio_base;
        void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
        const u32 cmd_fis_len = 5; /* five dwords */
        const char *reason = NULL;
        struct ata_taskfile tf;
+       u32 tmp;
        u8 *fis;
        int rc;
 
        DPRINTK("ENTER\n");
 
+       if (ata_port_offline(ap)) {
+               DPRINTK("PHY reports no device\n");
+               *class = ATA_DEV_NONE;
+               return 0;
+       }
+
        /* prepare for SRST (AHCI-1.1 10.4.1) */
        rc = ahci_stop_engine(ap);
        if (rc) {
@@ -558,23 +598,13 @@ static int ahci_softreset(struct ata_port *ap, int verbose, unsigned int *class)
        /* check BUSY/DRQ, perform Command List Override if necessary */
        ahci_tf_read(ap, &tf);
        if (tf.command & (ATA_BUSY | ATA_DRQ)) {
-               u32 tmp;
+               rc = ahci_clo(ap);
 
-               if (!(hpriv->cap & HOST_CAP_CLO)) {
-                       rc = -EIO;
-                       reason = "port busy but no CLO";
+               if (rc == -EOPNOTSUPP) {
+                       reason = "port busy but CLO unavailable";
                        goto fail_restart;
-               }
-
-               tmp = readl(port_mmio + PORT_CMD);
-               tmp |= PORT_CMD_CLO;
-               writel(tmp, port_mmio + PORT_CMD);
-               readl(port_mmio + PORT_CMD); /* flush */
-
-               if (ahci_poll_register(port_mmio + PORT_CMD, PORT_CMD_CLO, 0x0,
-                                      1, 500)) {
-                       rc = -EIO;
-                       reason = "CLO failed";
+               } else if (rc) {
+                       reason = "port busy but CLO failed";
                        goto fail_restart;
                }
        }
@@ -582,20 +612,21 @@ static int ahci_softreset(struct ata_port *ap, int verbose, unsigned int *class)
        /* restart engine */
        ahci_start_engine(ap);
 
-       ata_tf_init(ap, &tf, 0);
+       ata_tf_init(ap->device, &tf);
        fis = pp->cmd_tbl;
 
        /* issue the first D2H Register FIS */
-       ahci_fill_cmd_slot(pp, cmd_fis_len | AHCI_CMD_RESET | AHCI_CMD_CLR_BUSY);
+       ahci_fill_cmd_slot(pp, 0,
+                          cmd_fis_len | AHCI_CMD_RESET | AHCI_CMD_CLR_BUSY);
 
        tf.ctl |= ATA_SRST;
        ata_tf_to_fis(&tf, fis, 0);
        fis[1] &= ~(1 << 7);    /* turn off Command FIS bit */
 
        writel(1, port_mmio + PORT_CMD_ISSUE);
-       readl(port_mmio + PORT_CMD_ISSUE);      /* flush */
 
-       if (ahci_poll_register(port_mmio + PORT_CMD_ISSUE, 0x1, 0x0, 1, 500)) {
+       tmp = ata_wait_register(port_mmio + PORT_CMD_ISSUE, 0x1, 0x1, 1, 500);
+       if (tmp & 0x1) {
                rc = -EIO;
                reason = "1st FIS failed";
                goto fail;
@@ -605,7 +636,7 @@ static int ahci_softreset(struct ata_port *ap, int verbose, unsigned int *class)
        msleep(1);
 
        /* issue the second D2H Register FIS */
-       ahci_fill_cmd_slot(pp, cmd_fis_len);
+       ahci_fill_cmd_slot(pp, 0, cmd_fis_len);
 
        tf.ctl &= ~ATA_SRST;
        ata_tf_to_fis(&tf, fis, 0);
@@ -625,7 +656,7 @@ static int ahci_softreset(struct ata_port *ap, int verbose, unsigned int *class)
        msleep(150);
 
        *class = ATA_DEV_NONE;
-       if (sata_dev_present(ap)) {
+       if (ata_port_online(ap)) {
                if (ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT)) {
                        rc = -EIO;
                        reason = "device not ready";
@@ -640,25 +671,21 @@ static int ahci_softreset(struct ata_port *ap, int verbose, unsigned int *class)
  fail_restart:
        ahci_start_engine(ap);
  fail:
-       if (verbose)
-               printk(KERN_ERR "ata%u: softreset failed (%s)\n",
-                      ap->id, reason);
-       else
-               DPRINTK("EXIT, rc=%d reason=\"%s\"\n", rc, reason);
+       ata_port_printk(ap, KERN_ERR, "softreset failed (%s)\n", reason);
        return rc;
 }
 
-static int ahci_hardreset(struct ata_port *ap, int verbose, unsigned int *class)
+static int ahci_hardreset(struct ata_port *ap, unsigned int *class)
 {
        int rc;
 
        DPRINTK("ENTER\n");
 
        ahci_stop_engine(ap);
-       rc = sata_std_hardreset(ap, verbose, class);
+       rc = sata_std_hardreset(ap, class);
        ahci_start_engine(ap);
 
-       if (rc == 0)
+       if (rc == 0 && ata_port_online(ap))
                *class = ahci_dev_classify(ap);
        if (*class == ATA_DEV_UNKNOWN)
                *class = ATA_DEV_NONE;
@@ -688,6 +715,12 @@ static void ahci_postreset(struct ata_port *ap, unsigned int *class)
 
 static int ahci_probe_reset(struct ata_port *ap, unsigned int *classes)
 {
+       if ((ap->flags & AHCI_FLAG_RESET_NEEDS_CLO) &&
+           (ata_busy_wait(ap, ATA_BUSY, 1000) & ATA_BUSY)) {
+               /* ATA_BUSY hasn't cleared, so send a CLO */
+               ahci_clo(ap);
+       }
+
        return ata_drive_probe_reset(ap, ata_std_probeinit,
                                     ahci_softreset, ahci_hardreset,
                                     ahci_postreset, classes);
@@ -708,9 +741,8 @@ static void ahci_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
        ata_tf_from_fis(d2h_fis, tf);
 }
 
-static unsigned int ahci_fill_sg(struct ata_queued_cmd *qc)
+static unsigned int ahci_fill_sg(struct ata_queued_cmd *qc, void *cmd_tbl)
 {
-       struct ahci_port_priv *pp = qc->ap->private_data;
        struct scatterlist *sg;
        struct ahci_sg *ahci_sg;
        unsigned int n_sg = 0;
@@ -720,7 +752,7 @@ static unsigned int ahci_fill_sg(struct ata_queued_cmd *qc)
        /*
         * Next, the S/G list.
         */
-       ahci_sg = pp->cmd_tbl_sg;
+       ahci_sg = cmd_tbl + AHCI_CMD_TBL_HDR_SZ;
        ata_for_each_sg(sg, qc) {
                dma_addr_t addr = sg_dma_address(sg);
                u32 sg_len = sg_dma_len(sg);
@@ -741,6 +773,7 @@ static void ahci_qc_prep(struct ata_queued_cmd *qc)
        struct ata_port *ap = qc->ap;
        struct ahci_port_priv *pp = ap->private_data;
        int is_atapi = is_atapi_taskfile(&qc->tf);
+       void *cmd_tbl;
        u32 opts;
        const u32 cmd_fis_len = 5; /* five dwords */
        unsigned int n_elem;
@@ -749,16 +782,17 @@ static void ahci_qc_prep(struct ata_queued_cmd *qc)
         * Fill in command table information.  First, the header,
         * a SATA Register - Host to Device command FIS.
         */
-       ata_tf_to_fis(&qc->tf, pp->cmd_tbl, 0);
+       cmd_tbl = pp->cmd_tbl + qc->tag * AHCI_CMD_TBL_SZ;
+
+       ata_tf_to_fis(&qc->tf, cmd_tbl, 0);
        if (is_atapi) {
-               memset(pp->cmd_tbl + AHCI_CMD_TBL_CDB, 0, 32);
-               memcpy(pp->cmd_tbl + AHCI_CMD_TBL_CDB, qc->cdb,
-                      qc->dev->cdb_len);
+               memset(cmd_tbl + AHCI_CMD_TBL_CDB, 0, 32);
+               memcpy(cmd_tbl + AHCI_CMD_TBL_CDB, qc->cdb, qc->dev->cdb_len);
        }
 
        n_elem = 0;
        if (qc->flags & ATA_QCFLAG_DMAMAP)
-               n_elem = ahci_fill_sg(qc);
+               n_elem = ahci_fill_sg(qc, cmd_tbl);
 
        /*
         * Fill in command slot information.
@@ -769,112 +803,123 @@ static void ahci_qc_prep(struct ata_queued_cmd *qc)
        if (is_atapi)
                opts |= AHCI_CMD_ATAPI | AHCI_CMD_PREFETCH;
 
-       ahci_fill_cmd_slot(pp, opts);
+       ahci_fill_cmd_slot(pp, qc->tag, opts);
 }
 
-static void ahci_restart_port(struct ata_port *ap, u32 irq_stat)
+static void ahci_error_intr(struct ata_port *ap, u32 irq_stat)
 {
-       void __iomem *mmio = ap->host_set->mmio_base;
-       void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
-       u32 tmp;
+       struct ahci_port_priv *pp = ap->private_data;
+       struct ata_eh_info *ehi = &ap->eh_info;
+       unsigned int err_mask = 0, action = 0;
+       struct ata_queued_cmd *qc;
+       u32 serror;
 
-       if ((ap->device[0].class != ATA_DEV_ATAPI) ||
-           ((irq_stat & PORT_IRQ_TF_ERR) == 0))
-               printk(KERN_WARNING "ata%u: port reset, "
-                      "p_is %x is %x pis %x cmd %x tf %x ss %x se %x\n",
-                       ap->id,
-                       irq_stat,
-                       readl(mmio + HOST_IRQ_STAT),
-                       readl(port_mmio + PORT_IRQ_STAT),
-                       readl(port_mmio + PORT_CMD),
-                       readl(port_mmio + PORT_TFDATA),
-                       readl(port_mmio + PORT_SCR_STAT),
-                       readl(port_mmio + PORT_SCR_ERR));
-
-       /* stop DMA */
-       ahci_stop_engine(ap);
+       ata_ehi_clear_desc(ehi);
 
-       /* clear SATA phy error, if any */
-       tmp = readl(port_mmio + PORT_SCR_ERR);
-       writel(tmp, port_mmio + PORT_SCR_ERR);
+       /* AHCI needs SError cleared; otherwise, it might lock up */
+       serror = ahci_scr_read(ap, SCR_ERROR);
+       ahci_scr_write(ap, SCR_ERROR, serror);
 
-       /* if DRQ/BSY is set, device needs to be reset.
-        * if so, issue COMRESET
-        */
-       tmp = readl(port_mmio + PORT_TFDATA);
-       if (tmp & (ATA_BUSY | ATA_DRQ)) {
-               writel(0x301, port_mmio + PORT_SCR_CTL);
-               readl(port_mmio + PORT_SCR_CTL); /* flush */
-               udelay(10);
-               writel(0x300, port_mmio + PORT_SCR_CTL);
-               readl(port_mmio + PORT_SCR_CTL); /* flush */
+       /* analyze @irq_stat */
+       ata_ehi_push_desc(ehi, "irq_stat 0x%08x", irq_stat);
+
+       if (irq_stat & PORT_IRQ_TF_ERR)
+               err_mask |= AC_ERR_DEV;
+
+       if (irq_stat & (PORT_IRQ_HBUS_ERR | PORT_IRQ_HBUS_DATA_ERR)) {
+               err_mask |= AC_ERR_HOST_BUS;
+               action |= ATA_EH_SOFTRESET;
        }
 
-       /* re-start DMA */
-       ahci_start_engine(ap);
-}
+       if (irq_stat & PORT_IRQ_IF_ERR) {
+               err_mask |= AC_ERR_ATA_BUS;
+               action |= ATA_EH_SOFTRESET;
+               ata_ehi_push_desc(ehi, ", interface fatal error");
+       }
 
-static void ahci_eng_timeout(struct ata_port *ap)
-{
-       struct ata_host_set *host_set = ap->host_set;
-       void __iomem *mmio = host_set->mmio_base;
-       void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
-       struct ata_queued_cmd *qc;
-       unsigned long flags;
+       if (irq_stat & (PORT_IRQ_CONNECT | PORT_IRQ_PHYRDY)) {
+               err_mask |= AC_ERR_ATA_BUS;
+               action |= ATA_EH_SOFTRESET;
+               ata_ehi_push_desc(ehi, ", %s", irq_stat & PORT_IRQ_CONNECT ?
+                       "connection status changed" : "PHY RDY changed");
+       }
 
-       printk(KERN_WARNING "ata%u: handling error/timeout\n", ap->id);
+       if (irq_stat & PORT_IRQ_UNK_FIS) {
+               u32 *unk = (u32 *)(pp->rx_fis + RX_FIS_UNK);
 
-       spin_lock_irqsave(&host_set->lock, flags);
+               err_mask |= AC_ERR_HSM;
+               action |= ATA_EH_SOFTRESET;
+               ata_ehi_push_desc(ehi, ", unknown FIS %08x %08x %08x %08x",
+                                 unk[0], unk[1], unk[2], unk[3]);
+       }
 
-       ahci_restart_port(ap, readl(port_mmio + PORT_IRQ_STAT));
-       qc = ata_qc_from_tag(ap, ap->active_tag);
-       qc->err_mask |= AC_ERR_TIMEOUT;
+       /* okay, let's hand over to EH */
+       ehi->serror |= serror;
+       ehi->action |= action;
 
-       spin_unlock_irqrestore(&host_set->lock, flags);
+       qc = ata_qc_from_tag(ap, ap->active_tag);
+       if (qc)
+               qc->err_mask |= err_mask;
+       else
+               ehi->err_mask |= err_mask;
 
-       ata_eh_qc_complete(qc);
+       if (irq_stat & PORT_IRQ_FREEZE)
+               ata_port_freeze(ap);
+       else
+               ata_port_abort(ap);
 }
 
-static inline int ahci_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc)
+static void ahci_host_intr(struct ata_port *ap)
 {
        void __iomem *mmio = ap->host_set->mmio_base;
        void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
-       u32 status, serr, ci;
-
-       serr = readl(port_mmio + PORT_SCR_ERR);
-       writel(serr, port_mmio + PORT_SCR_ERR);
+       struct ata_eh_info *ehi = &ap->eh_info;
+       u32 status, qc_active;
+       int rc;
 
        status = readl(port_mmio + PORT_IRQ_STAT);
        writel(status, port_mmio + PORT_IRQ_STAT);
 
-       ci = readl(port_mmio + PORT_CMD_ISSUE);
-       if (likely((ci & 0x1) == 0)) {
-               if (qc) {
-                       WARN_ON(qc->err_mask);
-                       ata_qc_complete(qc);
-                       qc = NULL;
-               }
+       if (unlikely(status & PORT_IRQ_ERROR)) {
+               ahci_error_intr(ap, status);
+               return;
        }
 
-       if (status & PORT_IRQ_FATAL) {
-               unsigned int err_mask;
-               if (status & PORT_IRQ_TF_ERR)
-                       err_mask = AC_ERR_DEV;
-               else if (status & PORT_IRQ_IF_ERR)
-                       err_mask = AC_ERR_ATA_BUS;
-               else
-                       err_mask = AC_ERR_HOST_BUS;
-
-               /* command processing has stopped due to error; restart */
-               ahci_restart_port(ap, status);
-
-               if (qc) {
-                       qc->err_mask |= err_mask;
-                       ata_qc_complete(qc);
-               }
+       if (ap->sactive)
+               qc_active = readl(port_mmio + PORT_SCR_ACT);
+       else
+               qc_active = readl(port_mmio + PORT_CMD_ISSUE);
+
+       rc = ata_qc_complete_multiple(ap, qc_active, NULL);
+       if (rc > 0)
+               return;
+       if (rc < 0) {
+               ehi->err_mask |= AC_ERR_HSM;
+               ehi->action |= ATA_EH_SOFTRESET;
+               ata_port_freeze(ap);
+               return;
+       }
+
+       /* hmmm... a spurious interupt */
+
+       /* some devices send D2H reg with I bit set during NCQ command phase */
+       if (ap->sactive && status & PORT_IRQ_D2H_REG_FIS)
+               return;
+
+       /* ignore interim PIO setup fis interrupts */
+       if (ata_tag_valid(ap->active_tag)) {
+               struct ata_queued_cmd *qc =
+                       ata_qc_from_tag(ap, ap->active_tag);
+
+               if (qc && qc->tf.protocol == ATA_PROT_PIO &&
+                   (status & PORT_IRQ_PIOS_FIS))
+                       return;
        }
 
-       return 1;
+       if (ata_ratelimit())
+               ata_port_printk(ap, KERN_INFO, "spurious interrupt "
+                               "(irq_stat 0x%x active_tag %d sactive 0x%x)\n",
+                               status, ap->active_tag, ap->sactive);
 }
 
 static void ahci_irq_clear(struct ata_port *ap)
@@ -882,7 +927,7 @@ static void ahci_irq_clear(struct ata_port *ap)
        /* TODO */
 }
 
-static irqreturn_t ahci_interrupt (int irq, void *dev_instance, struct pt_regs *regs)
+static irqreturn_t ahci_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
 {
        struct ata_host_set *host_set = dev_instance;
        struct ahci_host_priv *hpriv;
@@ -911,14 +956,7 @@ static irqreturn_t ahci_interrupt (int irq, void *dev_instance, struct pt_regs *
 
                ap = host_set->ports[i];
                if (ap) {
-                       struct ata_queued_cmd *qc;
-                       qc = ata_qc_from_tag(ap, ap->active_tag);
-                       if (!ahci_host_intr(ap, qc))
-                               if (ata_ratelimit())
-                                       dev_printk(KERN_WARNING, host_set->dev,
-                                         "unhandled interrupt on port %u\n",
-                                         i);
-
+                       ahci_host_intr(ap);
                        VPRINTK("port %u\n", i);
                } else {
                        VPRINTK("port %u (no irq)\n", i);
@@ -935,7 +973,7 @@ static irqreturn_t ahci_interrupt (int irq, void *dev_instance, struct pt_regs *
                handled = 1;
        }
 
-        spin_unlock(&host_set->lock);
+       spin_unlock(&host_set->lock);
 
        VPRINTK("EXIT\n");
 
@@ -947,12 +985,64 @@ static unsigned int ahci_qc_issue(struct ata_queued_cmd *qc)
        struct ata_port *ap = qc->ap;
        void __iomem *port_mmio = (void __iomem *) ap->ioaddr.cmd_addr;
 
-       writel(1, port_mmio + PORT_CMD_ISSUE);
+       if (qc->tf.protocol == ATA_PROT_NCQ)
+               writel(1 << qc->tag, port_mmio + PORT_SCR_ACT);
+       writel(1 << qc->tag, port_mmio + PORT_CMD_ISSUE);
        readl(port_mmio + PORT_CMD_ISSUE);      /* flush */
 
        return 0;
 }
 
+static void ahci_freeze(struct ata_port *ap)
+{
+       void __iomem *mmio = ap->host_set->mmio_base;
+       void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
+
+       /* turn IRQ off */
+       writel(0, port_mmio + PORT_IRQ_MASK);
+}
+
+static void ahci_thaw(struct ata_port *ap)
+{
+       void __iomem *mmio = ap->host_set->mmio_base;
+       void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
+       u32 tmp;
+
+       /* clear IRQ */
+       tmp = readl(port_mmio + PORT_IRQ_STAT);
+       writel(tmp, port_mmio + PORT_IRQ_STAT);
+       writel(1 << ap->id, mmio + HOST_IRQ_STAT);
+
+       /* turn IRQ back on */
+       writel(DEF_PORT_IRQ, port_mmio + PORT_IRQ_MASK);
+}
+
+static void ahci_error_handler(struct ata_port *ap)
+{
+       if (!(ap->flags & ATA_FLAG_FROZEN)) {
+               /* restart engine */
+               ahci_stop_engine(ap);
+               ahci_start_engine(ap);
+       }
+
+       /* perform recovery */
+       ata_do_eh(ap, ahci_softreset, ahci_hardreset, ahci_postreset);
+}
+
+static void ahci_post_internal_cmd(struct ata_queued_cmd *qc)
+{
+       struct ata_port *ap = qc->ap;
+
+       if (qc->flags & ATA_QCFLAG_FAILED)
+               qc->err_mask |= AC_ERR_OTHER;
+
+       if (qc->err_mask) {
+               /* make DMA engine forget about the failed command */
+               ahci_stop_engine(ap);
+               ahci_start_engine(ap);
+       }
+}
+
 static void ahci_setup_port(struct ata_ioports *port, unsigned long base,
                            unsigned int port_idx)
 {
@@ -1097,9 +1187,6 @@ static int ahci_host_init(struct ata_probe_ent *probe_ent)
                        writel(tmp, port_mmio + PORT_IRQ_STAT);
 
                writel(1 << i, mmio + HOST_IRQ_STAT);
-
-               /* set irq mask (enables interrupts) */
-               writel(DEF_PORT_IRQ, port_mmio + PORT_IRQ_MASK);
        }
 
        tmp = readl(mmio + HOST_CTL);
@@ -1197,6 +1284,8 @@ static int ahci_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
 
        VPRINTK("ENTER\n");
 
+       WARN_ON(ATA_MAX_QUEUE > AHCI_MAX_CMDS);
+
        if (!printed_version++)
                dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
 
@@ -1264,6 +1353,9 @@ static int ahci_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
        if (rc)
                goto err_out_hpriv;
 
+       if (hpriv->cap & HOST_CAP_NCQ)
+               probe_ent->host_flags |= ATA_FLAG_NCQ;
+
        ahci_print_info(probe_ent);
 
        /* FIXME: check ata_device_add return value */
index 6dc8814..28bd8ca 100644 (file)
@@ -93,7 +93,7 @@
 #include <linux/libata.h>
 
 #define DRV_NAME       "ata_piix"
-#define DRV_VERSION    "1.05"
+#define DRV_VERSION    "1.10"
 
 enum {
        PIIX_IOCFG              = 0x54, /* IDE I/O configuration register */
@@ -159,6 +159,7 @@ static const struct pci_device_id piix_pci_tbl[] = {
        { 0x8086, 0x7111, PCI_ANY_ID, PCI_ANY_ID, 0, 0, piix4_pata },
        { 0x8086, 0x24db, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_pata },
        { 0x8086, 0x25a2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_pata },
+       { 0x8086, 0x27df, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_pata },
 #endif
 
        /* NOTE: The following PCI ids must be kept in sync with the
@@ -243,7 +244,10 @@ static const struct ata_port_operations piix_pata_ops = {
        .qc_prep                = ata_qc_prep,
        .qc_issue               = ata_qc_issue_prot,
 
-       .eng_timeout            = ata_eng_timeout,
+       .freeze                 = ata_bmdma_freeze,
+       .thaw                   = ata_bmdma_thaw,
+       .error_handler          = ata_bmdma_error_handler,
+       .post_internal_cmd      = ata_bmdma_post_internal_cmd,
 
        .irq_handler            = ata_interrupt,
        .irq_clear              = ata_bmdma_irq_clear,
@@ -271,7 +275,10 @@ static const struct ata_port_operations piix_sata_ops = {
        .qc_prep                = ata_qc_prep,
        .qc_issue               = ata_qc_issue_prot,
 
-       .eng_timeout            = ata_eng_timeout,
+       .freeze                 = ata_bmdma_freeze,
+       .thaw                   = ata_bmdma_thaw,
+       .error_handler          = ata_bmdma_error_handler,
+       .post_internal_cmd      = ata_bmdma_post_internal_cmd,
 
        .irq_handler            = ata_interrupt,
        .irq_clear              = ata_bmdma_irq_clear,
@@ -484,7 +491,7 @@ static int piix_pata_probe_reset(struct ata_port *ap, unsigned int *classes)
        struct pci_dev *pdev = to_pci_dev(ap->host_set->dev);
 
        if (!pci_test_config_bits(pdev, &piix_enable_bits[ap->hard_port_no])) {
-               printk(KERN_INFO "ata%u: port disabled. ignoring.\n", ap->id);
+               ata_port_printk(ap, KERN_INFO, "port disabled. ignoring.\n");
                return 0;
        }
 
@@ -565,7 +572,7 @@ static unsigned int piix_sata_probe (struct ata_port *ap)
 static int piix_sata_probe_reset(struct ata_port *ap, unsigned int *classes)
 {
        if (!piix_sata_probe(ap)) {
-               printk(KERN_INFO "ata%u: SATA port has no device.\n", ap->id);
+               ata_port_printk(ap, KERN_INFO, "SATA port has no device.\n");
                return 0;
        }
 
index 835dff0..6d30d2c 100644 (file)
@@ -652,6 +652,149 @@ void ata_bmdma_stop(struct ata_queued_cmd *qc)
        ata_altstatus(ap);        /* dummy read */
 }
 
+/**
+ *     ata_bmdma_freeze - Freeze BMDMA controller port
+ *     @ap: port to freeze
+ *
+ *     Freeze BMDMA controller port.
+ *
+ *     LOCKING:
+ *     Inherited from caller.
+ */
+void ata_bmdma_freeze(struct ata_port *ap)
+{
+       struct ata_ioports *ioaddr = &ap->ioaddr;
+
+       ap->ctl |= ATA_NIEN;
+       ap->last_ctl = ap->ctl;
+
+       if (ap->flags & ATA_FLAG_MMIO)
+               writeb(ap->ctl, (void __iomem *)ioaddr->ctl_addr);
+       else
+               outb(ap->ctl, ioaddr->ctl_addr);
+}
+
+/**
+ *     ata_bmdma_thaw - Thaw BMDMA controller port
+ *     @ap: port to thaw
+ *
+ *     Thaw BMDMA controller port.
+ *
+ *     LOCKING:
+ *     Inherited from caller.
+ */
+void ata_bmdma_thaw(struct ata_port *ap)
+{
+       /* clear & re-enable interrupts */
+       ata_chk_status(ap);
+       ap->ops->irq_clear(ap);
+       if (ap->ioaddr.ctl_addr)        /* FIXME: hack. create a hook instead */
+               ata_irq_on(ap);
+}
+
+/**
+ *     ata_bmdma_drive_eh - Perform EH with given methods for BMDMA controller
+ *     @ap: port to handle error for
+ *     @softreset: softreset method (can be NULL)
+ *     @hardreset: hardreset method (can be NULL)
+ *     @postreset: postreset method (can be NULL)
+ *
+ *     Handle error for ATA BMDMA controller.  It can handle both
+ *     PATA and SATA controllers.  Many controllers should be able to
+ *     use this EH as-is or with some added handling before and
+ *     after.
+ *
+ *     This function is intended to be used for constructing
+ *     ->error_handler callback by low level drivers.
+ *
+ *     LOCKING:
+ *     Kernel thread context (may sleep)
+ */
+void ata_bmdma_drive_eh(struct ata_port *ap, ata_reset_fn_t softreset,
+                       ata_reset_fn_t hardreset, ata_postreset_fn_t postreset)
+{
+       struct ata_host_set *host_set = ap->host_set;
+       struct ata_eh_context *ehc = &ap->eh_context;
+       struct ata_queued_cmd *qc;
+       unsigned long flags;
+       int thaw = 0;
+
+       qc = __ata_qc_from_tag(ap, ap->active_tag);
+       if (qc && !(qc->flags & ATA_QCFLAG_FAILED))
+               qc = NULL;
+
+       /* reset PIO HSM and stop DMA engine */
+       spin_lock_irqsave(&host_set->lock, flags);
+
+       ap->hsm_task_state = HSM_ST_IDLE;
+
+       if (qc && (qc->tf.protocol == ATA_PROT_DMA ||
+                  qc->tf.protocol == ATA_PROT_ATAPI_DMA)) {
+               u8 host_stat;
+
+               host_stat = ata_bmdma_status(ap);
+
+               ata_ehi_push_desc(&ehc->i, "BMDMA stat 0x%x", host_stat);
+
+               /* BMDMA controllers indicate host bus error by
+                * setting DMA_ERR bit and timing out.  As it wasn't
+                * really a timeout event, adjust error mask and
+                * cancel frozen state.
+                */
+               if (qc->err_mask == AC_ERR_TIMEOUT && host_stat & ATA_DMA_ERR) {
+                       qc->err_mask = AC_ERR_HOST_BUS;
+                       thaw = 1;
+               }
+
+               ap->ops->bmdma_stop(qc);
+       }
+
+       ata_altstatus(ap);
+       ata_chk_status(ap);
+       ap->ops->irq_clear(ap);
+
+       spin_unlock_irqrestore(&host_set->lock, flags);
+
+       if (thaw)
+               ata_eh_thaw_port(ap);
+
+       /* PIO and DMA engines have been stopped, perform recovery */
+       ata_do_eh(ap, softreset, hardreset, postreset);
+}
+
+/**
+ *     ata_bmdma_error_handler - Stock error handler for BMDMA controller
+ *     @ap: port to handle error for
+ *
+ *     Stock error handler for BMDMA controller.
+ *
+ *     LOCKING:
+ *     Kernel thread context (may sleep)
+ */
+void ata_bmdma_error_handler(struct ata_port *ap)
+{
+       ata_reset_fn_t hardreset;
+
+       hardreset = NULL;
+       if (sata_scr_valid(ap))
+               hardreset = sata_std_hardreset;
+
+       ata_bmdma_drive_eh(ap, ata_std_softreset, hardreset, ata_std_postreset);
+}
+
+/**
+ *     ata_bmdma_post_internal_cmd - Stock post_internal_cmd for
+ *                                   BMDMA controller
+ *     @qc: internal command to clean up
+ *
+ *     LOCKING:
+ *     Kernel thread context (may sleep)
+ */
+void ata_bmdma_post_internal_cmd(struct ata_queued_cmd *qc)
+{
+       ata_bmdma_stop(qc);
+}
+
 #ifdef CONFIG_PCI
 static struct ata_probe_ent *
 ata_probe_ent_alloc(struct device *dev, const struct ata_port_info *port)
index fa476e7..e891b83 100644 (file)
 
 #include "libata.h"
 
-static unsigned int ata_dev_init_params(struct ata_port *ap,
-                                       struct ata_device *dev,
-                                       u16 heads,
-                                       u16 sectors);
-static void ata_set_mode(struct ata_port *ap);
-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;
@@ -77,6 +73,10 @@ int atapi_enabled = 1;
 module_param(atapi_enabled, int, 0444);
 MODULE_PARM_DESC(atapi_enabled, "Enable discovery of ATAPI devices (0=off, 1=on)");
 
+int atapi_dmadir = 0;
+module_param(atapi_dmadir, int, 0444);
+MODULE_PARM_DESC(atapi_dmadir, "Enable ATAPI DMADIR bridge support (0=off, 1=on)");
+
 int libata_fua = 0;
 module_param_named(fua, libata_fua, int, 0444);
 MODULE_PARM_DESC(fua, "FUA support (0=off, 1=on)");
@@ -397,11 +397,22 @@ static const char *ata_mode_string(unsigned int xfer_mask)
        return "<n/a>";
 }
 
-static void ata_dev_disable(struct ata_port *ap, struct ata_device *dev)
+static const char *sata_spd_string(unsigned int spd)
+{
+       static const char * const spd_str[] = {
+               "1.5 Gbps",
+               "3.0 Gbps",
+       };
+
+       if (spd == 0 || (spd - 1) >= ARRAY_SIZE(spd_str))
+               return "<unknown>";
+       return spd_str[spd - 1];
+}
+
+void ata_dev_disable(struct ata_device *dev)
 {
-       if (ata_dev_present(dev)) {
-               printk(KERN_WARNING "ata%u: dev %u disabled\n",
-                      ap->id, dev->devno);
+       if (ata_dev_enabled(dev)) {
+               ata_dev_printk(dev, KERN_WARNING, "disabled\n");
                dev->class++;
        }
 }
@@ -943,15 +954,14 @@ void ata_qc_complete_internal(struct ata_queued_cmd *qc)
 {
        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
  *     @dma_dir: Data tranfer direction of the command
  *     @buf: Data buffer of the command
  *     @buflen: Length of data buffer
@@ -966,23 +976,62 @@ void ata_qc_complete_internal(struct ata_queued_cmd *qc)
  *     None.  Should be called with kernel context, might sleep.
  */
 
-static unsigned
-ata_exec_internal(struct ata_port *ap, struct ata_device *dev,
-                 struct ata_taskfile *tf,
-                 int dma_dir, void *buf, unsigned int buflen)
+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;
+       u32 preempted_sactive, preempted_qc_active;
        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->qc_allocated))
+               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;
+       preempted_sactive = ap->sactive;
+       preempted_qc_active = ap->qc_active;
+       ap->active_tag = ATA_TAG_POISON;
+       ap->sactive = 0;
+       ap->qc_active = 0;
 
+       /* 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);
@@ -996,31 +1045,53 @@ ata_exec_internal(struct ata_port *ap, struct ata_device *dev,
 
        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;
+       ap->sactive = preempted_sactive;
+       ap->qc_active = preempted_qc_active;
 
        /* XXX - Some LLDDs (sata_mv) disable port on command failure.
         * Until those drivers are fixed, we detect the condition
@@ -1033,11 +1104,13 @@ ata_exec_internal(struct ata_port *ap, struct ata_device *dev,
         *
         * Kill the following code as soon as those drivers are fixed.
         */
-       if (ap->flags & ATA_FLAG_PORT_DISABLED) {
+       if (ap->flags & ATA_FLAG_DISABLED) {
                err_mask |= AC_ERR_SYSTEM;
                ata_port_probe(ap);
        }
 
+       spin_unlock_irqrestore(&ap->host_set->lock, flags);
+
        return err_mask;
 }
 
@@ -1076,11 +1149,10 @@ unsigned int ata_pio_need_iordy(const struct ata_device *adev)
 
 /**
  *     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
@@ -1093,13 +1165,13 @@ unsigned int ata_pio_need_iordy(const struct ata_device *adev)
  *     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;
 
@@ -1107,15 +1179,8 @@ static int ata_dev_read_id(struct ata_port *ap, struct ata_device *dev,
 
        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:
@@ -1132,7 +1197,7 @@ static int ata_dev_read_id(struct ata_port *ap, struct ata_device *dev,
 
        tf.protocol = ATA_PROT_PIO;
 
-       err_mask = ata_exec_internal(ap, dev, &tf, 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;
@@ -1159,7 +1224,7 @@ static int ata_dev_read_id(struct ata_port *ap, struct ata_device *dev,
                 * 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";
@@ -1175,25 +1240,44 @@ static int ata_dev_read_id(struct ata_port *ap, struct ata_device *dev,
        }
 
        *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 ((dev->ap->cbl == ATA_CBL_SATA) && (!ata_id_is_sata(dev->id)));
+}
+
+static void ata_dev_config_ncq(struct ata_device *dev,
+                              char *desc, size_t desc_sz)
 {
-       return ((ap->cbl == ATA_CBL_SATA) && (!ata_id_is_sata(dev->id)));
+       struct ata_port *ap = dev->ap;
+       int hdepth = 0, ddepth = ata_id_queue_depth(dev->id);
+
+       if (!ata_id_has_ncq(dev->id)) {
+               desc[0] = '\0';
+               return;
+       }
+
+       if (ap->flags & ATA_FLAG_NCQ) {
+               hdepth = min(ap->host->can_queue, ATA_MAX_QUEUE - 1);
+               dev->flags |= ATA_DFLAG_NCQ;
+       }
+
+       if (hdepth >= ddepth)
+               snprintf(desc, desc_sz, "NCQ (depth %d)", ddepth);
+       else
+               snprintf(desc, desc_sz, "NCQ (depth %d/%d)", hdepth, ddepth);
 }
 
 /**
  *     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
  *
@@ -1206,14 +1290,14 @@ static inline u8 ata_dev_knobble(const struct ata_port *ap,
  *     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;
 
-       if (!ata_dev_present(dev)) {
+       if (!ata_dev_enabled(dev)) {
                DPRINTK("ENTER/EXIT (host %u, dev %u) -- nodev\n",
                        ap->id, dev->devno);
                return 0;
@@ -1223,13 +1307,13 @@ static int ata_dev_configure(struct ata_port *ap, struct ata_device *dev,
 
        /* 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 = 0;
+       dev->flags &= ~ATA_DFLAG_CFG_MASK;
        dev->max_sectors = 0;
        dev->cdb_len = 0;
        dev->n_sectors = 0;
@@ -1252,6 +1336,7 @@ static int ata_dev_configure(struct ata_port *ap, struct ata_device *dev,
 
                if (ata_id_has_lba(id)) {
                        const char *lba_desc;
+                       char ncq_desc[20];
 
                        lba_desc = "LBA";
                        dev->flags |= ATA_DFLAG_LBA;
@@ -1260,15 +1345,17 @@ static int ata_dev_configure(struct ata_port *ap, struct ata_device *dev,
                                lba_desc = "LBA48";
                        }
 
+                       /* config NCQ */
+                       ata_dev_config_ncq(dev, ncq_desc, sizeof(ncq_desc));
+
                        /* 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 %s\n",
+                                       ata_id_major_version(id),
+                                       ata_mode_string(xfer_mask),
+                                       (unsigned long long)dev->n_sectors,
+                                       lba_desc, ncq_desc);
                } else {
                        /* CHS */
 
@@ -1286,13 +1373,18 @@ static int ata_dev_configure(struct ata_port *ap, struct ata_device *dev,
 
                        /* 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;
@@ -1300,18 +1392,27 @@ static int ata_dev_configure(struct ata_port *ap, struct ata_device *dev,
 
        /* 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)
-                       printk(KERN_INFO "ata%u: dev %u ATAPI, max %s\n",
-                              ap->id, dev->devno, ata_mode_string(xfer_mask));
+                       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;
@@ -1321,10 +1422,10 @@ static int ata_dev_configure(struct ata_port *ap, struct ata_device *dev,
                                              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;
        }
@@ -1352,16 +1453,24 @@ err_out_nosup:
  *     PCI/etc. bus probe sem.
  *
  *     RETURNS:
- *     Zero on success, non-zero on error.
+ *     Zero on success, negative errno otherwise.
  */
 
 static int ata_bus_probe(struct ata_port *ap)
 {
        unsigned int classes[ATA_MAX_DEVICES];
-       unsigned int i, rc, found = 0;
+       int tries[ATA_MAX_DEVICES];
+       int i, rc, down_xfermask;
+       struct ata_device *dev;
 
        ata_port_probe(ap);
 
+       for (i = 0; i < ATA_MAX_DEVICES; i++)
+               tries[i] = ATA_PROBE_MAX_TRIES;
+
+ retry:
+       down_xfermask = 0;
+
        /* reset and determine device classes */
        for (i = 0; i < ATA_MAX_DEVICES; i++)
                classes[i] = ATA_DEV_UNKNOWN;
@@ -1369,15 +1478,18 @@ static int ata_bus_probe(struct ata_port *ap)
        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_PORT_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);
        }
@@ -1388,43 +1500,61 @@ static int ata_bus_probe(struct ata_port *ap)
 
        /* read IDENTIFY page and configure devices */
        for (i = 0; i < ATA_MAX_DEVICES; i++) {
-               struct ata_device *dev = &ap->device[i];
+               dev = &ap->device[i];
 
-               dev->class = classes[i];
+               if (tries[i])
+                       dev->class = classes[i];
 
-               if (!ata_dev_present(dev))
+               if (!ata_dev_enabled(dev))
                        continue;
 
-               WARN_ON(dev->id != NULL);
-               if (ata_dev_read_id(ap, dev, &dev->class, 1, &dev->id)) {
-                       dev->class = ATA_DEV_NONE;
-                       continue;
-               }
+               rc = ata_dev_read_id(dev, &dev->class, 1, dev->id);
+               if (rc)
+                       goto fail;
 
-               if (ata_dev_configure(ap, dev, 1)) {
-                       ata_dev_disable(ap, dev);
-                       continue;
-               }
+               rc = ata_dev_configure(dev, 1);
+               if (rc)
+                       goto fail;
+       }
 
-               found = 1;
+       /* configure transfer mode */
+       rc = ata_set_mode(ap, &dev);
+       if (rc) {
+               down_xfermask = 1;
+               goto fail;
        }
 
-       if (!found)
-               goto err_out_disable;
+       for (i = 0; i < ATA_MAX_DEVICES; i++)
+               if (ata_dev_enabled(&ap->device[i]))
+                       return 0;
 
-       if (ap->ops->set_mode)
-               ap->ops->set_mode(ap);
-       else
-               ata_set_mode(ap);
+       /* no device present, disable port */
+       ata_port_disable(ap);
+       ap->ops->port_disable(ap);
+       return -ENODEV;
 
-       if (ap->flags & ATA_FLAG_PORT_DISABLED)
-               goto err_out_disable;
+ fail:
+       switch (rc) {
+       case -EINVAL:
+       case -ENODEV:
+               tries[dev->devno] = 0;
+               break;
+       case -EIO:
+               sata_down_spd_limit(ap);
+               /* fall through */
+       default:
+               tries[dev->devno]--;
+               if (down_xfermask &&
+                   ata_down_xfermask_limit(dev, tries[dev->devno] == 1))
+                       tries[dev->devno] = 0;
+       }
 
-       return 0;
+       if (!tries[dev->devno]) {
+               ata_down_xfermask_limit(dev, 1);
+               ata_dev_disable(dev);
+       }
 
-err_out_disable:
-       ap->ops->port_disable(ap);
-       return -1;
+       goto retry;
 }
 
 /**
@@ -1440,7 +1570,7 @@ err_out_disable:
 
 void ata_port_probe(struct ata_port *ap)
 {
-       ap->flags &= ~ATA_FLAG_PORT_DISABLED;
+       ap->flags &= ~ATA_FLAG_DISABLED;
 }
 
 /**
@@ -1454,27 +1584,21 @@ void ata_port_probe(struct ata_port *ap)
  */
 static void sata_print_link_status(struct ata_port *ap)
 {
-       u32 sstatus, tmp;
-       const char *speed;
+       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);
-
-       if (sata_dev_present(ap)) {
+       if (ata_port_online(ap)) {
                tmp = (sstatus >> 4) & 0xf;
-               if (tmp & (1 << 0))
-                       speed = "1.5";
-               else if (tmp & (1 << 1))
-                       speed = "3.0";
-               else
-                       speed = "<unknown>";
-               printk(KERN_INFO "ata%u: SATA link up %s Gbps (SStatus %X)\n",
-                      ap->id, speed, sstatus);
+               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)\n",
-                      ap->id, sstatus);
+               ata_port_printk(ap, KERN_INFO,
+                               "SATA link down (SStatus %X SControl %X)\n",
+                               sstatus, scontrol);
        }
 }
 
@@ -1497,17 +1621,18 @@ void __sata_phy_reset(struct ata_port *ap)
 
        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));
@@ -1516,12 +1641,12 @@ void __sata_phy_reset(struct ata_port *ap)
        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);
 
-       if (ap->flags & ATA_FLAG_PORT_DISABLED)
+       if (ap->flags & ATA_FLAG_DISABLED)
                return;
 
        if (ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT)) {
@@ -1546,24 +1671,24 @@ void __sata_phy_reset(struct ata_port *ap)
 void sata_phy_reset(struct ata_port *ap)
 {
        __sata_phy_reset(ap);
-       if (ap->flags & ATA_FLAG_PORT_DISABLED)
+       if (ap->flags & ATA_FLAG_DISABLED)
                return;
        ata_bus_reset(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_present(pair))
+       if (!ata_dev_enabled(pair))
                return NULL;
        return pair;
 }
@@ -1585,7 +1710,122 @@ void ata_port_disable(struct ata_port *ap)
 {
        ap->device[0].class = ATA_DEV_NONE;
        ap->device[1].class = ATA_DEV_NONE;
-       ap->flags |= ATA_FLAG_PORT_DISABLED;
+       ap->flags |= ATA_FLAG_DISABLED;
+}
+
+/**
+ *     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 sata_set_spd().
+ *
+ *     LOCKING:
+ *     Inherited from caller.
+ *
+ *     RETURNS:
+ *     0 on success, negative errno on failure
+ */
+int sata_down_spd_limit(struct ata_port *ap)
+{
+       u32 sstatus, spd, mask;
+       int rc, highbit;
+
+       rc = sata_scr_read(ap, SCR_STATUS, &sstatus);
+       if (rc)
+               return rc;
+
+       mask = ap->sata_spd_limit;
+       if (mask <= 1)
+               return -EINVAL;
+       highbit = fls(mask) - 1;
+       mask &= ~(1 << highbit);
+
+       spd = (sstatus >> 4) & 0xf;
+       if (spd <= 1)
+               return -EINVAL;
+       spd--;
+       mask &= (1 << spd) - 1;
+       if (!mask)
+               return -EINVAL;
+
+       ap->sata_spd_limit = mask;
+
+       ata_port_printk(ap, KERN_WARNING, "limiting SATA link speed to %s\n",
+                       sata_spd_string(fls(mask)));
+
+       return 0;
+}
+
+static int __sata_set_spd_needed(struct ata_port *ap, u32 *scontrol)
+{
+       u32 spd, limit;
+
+       if (ap->sata_spd_limit == UINT_MAX)
+               limit = 0;
+       else
+               limit = fls(ap->sata_spd_limit);
+
+       spd = (*scontrol >> 4) & 0xf;
+       *scontrol = (*scontrol & ~0xf0) | ((limit & 0xf) << 4);
+
+       return spd != limit;
+}
+
+/**
+ *     sata_set_spd_needed - is SATA spd configuration needed
+ *     @ap: Port in question
+ *
+ *     Test whether the spd limit in SControl matches
+ *     @ap->sata_spd_limit.  This function is used to determine
+ *     whether hardreset is necessary to apply SATA spd
+ *     configuration.
+ *
+ *     LOCKING:
+ *     Inherited from caller.
+ *
+ *     RETURNS:
+ *     1 if SATA spd configuration is needed, 0 otherwise.
+ */
+int sata_set_spd_needed(struct ata_port *ap)
+{
+       u32 scontrol;
+
+       if (sata_scr_read(ap, SCR_CONTROL, &scontrol))
+               return 0;
+
+       return __sata_set_spd_needed(ap, &scontrol);
+}
+
+/**
+ *     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.
+ *
+ *     LOCKING:
+ *     Inherited from caller.
+ *
+ *     RETURNS:
+ *     0 if spd doesn't need to be changed, 1 if spd has been
+ *     changed.  Negative errno if SCR registers are inaccessible.
+ */
+int sata_set_spd(struct ata_port *ap)
+{
+       u32 scontrol;
+       int rc;
+
+       if ((rc = sata_scr_read(ap, SCR_CONTROL, &scontrol)))
+               return rc;
+
+       if (!__sata_set_spd_needed(ap, &scontrol))
+               return 0;
+
+       if ((rc = sata_scr_write(ap, SCR_CONTROL, scontrol)))
+               return rc;
+
+       return 1;
 }
 
 /*
@@ -1736,151 +1976,196 @@ int ata_timing_compute(struct ata_device *adev, unsigned short speed,
        return 0;
 }
 
-static int ata_dev_set_mode(struct ata_port *ap, struct ata_device *dev)
+/**
+ *     ata_down_xfermask_limit - adjust dev xfer masks downward
+ *     @dev: Device to adjust xfer masks
+ *     @force_pio0: Force PIO0
+ *
+ *     Adjust xfer masks of @dev downward.  Note that this function
+ *     does not apply the change.  Invoking ata_set_mode() afterwards
+ *     will apply the limit.
+ *
+ *     LOCKING:
+ *     Inherited from caller.
+ *
+ *     RETURNS:
+ *     0 on success, negative errno on failure
+ */
+int ata_down_xfermask_limit(struct ata_device *dev, int force_pio0)
+{
+       unsigned long xfer_mask;
+       int highbit;
+
+       xfer_mask = ata_pack_xfermask(dev->pio_mask, dev->mwdma_mask,
+                                     dev->udma_mask);
+
+       if (!xfer_mask)
+               goto fail;
+       /* don't gear down to MWDMA from UDMA, go directly to PIO */
+       if (xfer_mask & ATA_MASK_UDMA)
+               xfer_mask &= ~ATA_MASK_MWDMA;
+
+       highbit = fls(xfer_mask) - 1;
+       xfer_mask &= ~(1 << highbit);
+       if (force_pio0)
+               xfer_mask &= 1 << ATA_SHIFT_PIO;
+       if (!xfer_mask)
+               goto fail;
+
+       ata_unpack_xfermask(xfer_mask, &dev->pio_mask, &dev->mwdma_mask,
+                           &dev->udma_mask);
+
+       ata_dev_printk(dev, KERN_WARNING, "limiting speed to %s\n",
+                      ata_mode_string(xfer_mask));
+
+       return 0;
+
+ fail:
+       return -EINVAL;
+}
+
+static int ata_dev_set_mode(struct ata_device *dev)
 {
        unsigned int err_mask;
        int rc;
 
+       dev->flags &= ~ATA_DFLAG_PIO;
        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);
-       if (rc) {
-               printk(KERN_ERR
-                      "ata%u: failed to revalidate after set xfermode\n",
-                      ap->id);
+       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)));
-       return 0;
-}
-
-static int ata_host_set_pio(struct ata_port *ap)
-{
-       int i;
-
-       for (i = 0; i < ATA_MAX_DEVICES; i++) {
-               struct ata_device *dev = &ap->device[i];
-
-               if (!ata_dev_present(dev))
-                       continue;
-
-               if (!dev->pio_mode) {
-                       printk(KERN_WARNING "ata%u: no PIO support for device %d.\n", ap->id, i);
-                       return -1;
-               }
-
-               dev->xfer_mode = dev->pio_mode;
-               dev->xfer_shift = ATA_SHIFT_PIO;
-               if (ap->ops->set_piomode)
-                       ap->ops->set_piomode(ap, dev);
-       }
-
+       ata_dev_printk(dev, KERN_INFO, "configured for %s\n",
+                      ata_mode_string(ata_xfer_mode2mask(dev->xfer_mode)));
        return 0;
 }
 
-static void ata_host_set_dma(struct ata_port *ap)
-{
-       int i;
-
-       for (i = 0; i < ATA_MAX_DEVICES; i++) {
-               struct ata_device *dev = &ap->device[i];
-
-               if (!ata_dev_present(dev) || !dev->dma_mode)
-                       continue;
-
-               dev->xfer_mode = dev->dma_mode;
-               dev->xfer_shift = ata_xfer_mode2shift(dev->dma_mode);
-               if (ap->ops->set_dmamode)
-                       ap->ops->set_dmamode(ap, dev);
-       }
-}
-
 /**
  *     ata_set_mode - Program timings and issue SET FEATURES - XFER
  *     @ap: port on which timings will be programmed
+ *     @r_failed_dev: out paramter for failed device
  *
- *     Set ATA device disk transfer mode (PIO3, UDMA6, etc.).
+ *     Set ATA device disk transfer mode (PIO3, UDMA6, etc.).  If
+ *     ata_set_mode() fails, pointer to the failing device is
+ *     returned in @r_failed_dev.
  *
  *     LOCKING:
  *     PCI/etc. bus probe sem.
+ *
+ *     RETURNS:
+ *     0 on success, negative errno otherwise
  */
-static void ata_set_mode(struct ata_port *ap)
+int ata_set_mode(struct ata_port *ap, struct ata_device **r_failed_dev)
 {
-       int i, rc, used_dma = 0;
+       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++) {
-               struct ata_device *dev = &ap->device[i];
                unsigned int pio_mask, dma_mask;
 
-               if (!ata_dev_present(dev))
-                       continue;
+               dev = &ap->device[i];
 
-               ata_dev_xfermask(ap, dev);
+               if (!ata_dev_enabled(dev))
+                       continue;
 
-               /* TODO: let LLDD filter dev->*_mask here */
+               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);
                dev->pio_mode = ata_xfer_mask2mode(pio_mask);
                dev->dma_mode = ata_xfer_mask2mode(dma_mask);
 
+               found = 1;
                if (dev->dma_mode)
                        used_dma = 1;
        }
+       if (!found)
+               goto out;
 
        /* step 2: always set host PIO timings */
-       rc = ata_host_set_pio(ap);
-       if (rc)
-               goto err_out;
+       for (i = 0; i < ATA_MAX_DEVICES; i++) {
+               dev = &ap->device[i];
+               if (!ata_dev_enabled(dev))
+                       continue;
+
+               if (!dev->pio_mode) {
+                       ata_dev_printk(dev, KERN_WARNING, "no PIO support\n");
+                       rc = -EINVAL;
+                       goto out;
+               }
+
+               dev->xfer_mode = dev->pio_mode;
+               dev->xfer_shift = ATA_SHIFT_PIO;
+               if (ap->ops->set_piomode)
+                       ap->ops->set_piomode(ap, dev);
+       }
 
        /* step 3: set host DMA timings */
-       ata_host_set_dma(ap);
+       for (i = 0; i < ATA_MAX_DEVICES; i++) {
+               dev = &ap->device[i];
+
+               if (!ata_dev_enabled(dev) || !dev->dma_mode)
+                       continue;
+
+               dev->xfer_mode = dev->dma_mode;
+               dev->xfer_shift = ata_xfer_mode2shift(dev->dma_mode);
+               if (ap->ops->set_dmamode)
+                       ap->ops->set_dmamode(ap, dev);
+       }
 
        /* step 4: update devices' xfer mode */
        for (i = 0; i < ATA_MAX_DEVICES; i++) {
-               struct ata_device *dev = &ap->device[i];
+               dev = &ap->device[i];
 
-               if (!ata_dev_present(dev))
+               if (!ata_dev_enabled(dev))
                        continue;
 
-               if (ata_dev_set_mode(ap, dev))
-                       goto err_out;
+               rc = ata_dev_set_mode(dev);
+               if (rc)
+                       goto out;
        }
 
-       /*
-        *      Record simplex status. If we selected DMA then the other
-        *      host channels are not permitted to do so.
+       /* Record simplex status. If we selected DMA then the other
+        * host channels are not permitted to do so.
         */
-
        if (used_dma && (ap->host_set->flags & ATA_HOST_SIMPLEX))
                ap->host_set->simplex_claimed = 1;
 
-       /*
-        *      Chip specific finalisation
-        */
+       /* step5: chip specific finalisation */
        if (ap->ops->post_set_mode)
                ap->ops->post_set_mode(ap);
 
-       return;
-
-err_out:
-       ata_port_disable(ap);
+ out:
+       if (rc)
+               *r_failed_dev = dev;
+       return rc;
 }
 
 /**
@@ -1930,8 +2215,8 @@ unsigned int ata_busy_sleep (struct ata_port *ap,
        }
 
        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))) {
@@ -1940,8 +2225,8 @@ unsigned int ata_busy_sleep (struct ata_port *ap,
        }
 
        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;
        }
 
@@ -2033,8 +2318,10 @@ static unsigned int ata_bus_softreset(struct ata_port *ap,
         * the bus shows 0xFF because the odd clown forgets the D7
         * pulldown resistor.
         */
-       if (ata_check_status(ap) == 0xFF)
+       if (ata_check_status(ap) == 0xFF) {
+               ata_port_printk(ap, KERN_ERR, "SRST failed (status 0xFF)\n");
                return AC_ERR_OTHER;
+       }
 
        ata_bus_post_reset(ap, devmask);
 
@@ -2058,7 +2345,7 @@ static unsigned int ata_bus_softreset(struct ata_port *ap,
  *     Obtains host_set lock.
  *
  *     SIDE EFFECTS:
- *     Sets ATA_FLAG_PORT_DISABLED if bus reset fails.
+ *     Sets ATA_FLAG_DISABLED if bus reset fails.
  */
 
 void ata_bus_reset(struct ata_port *ap)
@@ -2126,7 +2413,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");
@@ -2135,19 +2422,27 @@ err_out:
 static int sata_phy_resume(struct ata_port *ap)
 {
        unsigned long timeout = jiffies + (HZ * 5);
-       u32 sstatus;
+       u32 scontrol, sstatus;
+       int rc;
 
-       scr_write_flush(ap, SCR_CONTROL, 0x300);
+       if ((rc = sata_scr_read(ap, SCR_CONTROL, &scontrol)))
+               return rc;
+
+       scontrol = (scontrol & 0x0f0) | 0x300;
+
+       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;
 }
 
 /**
@@ -2165,17 +2460,25 @@ static int sata_phy_resume(struct ata_port *ap)
  */
 void ata_std_probeinit(struct ata_port *ap)
 {
-       if ((ap->flags & ATA_FLAG_SATA) && ap->ops->scr_read) {
-               sata_phy_resume(ap);
-               if (sata_dev_present(ap))
-                       ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT);
+       u32 scontrol;
+
+       /* resume link */
+       sata_phy_resume(ap);
+
+       /* 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);
 }
 
 /**
  *     ata_std_softreset - reset host port via ATA SRST
  *     @ap: port to reset
- *     @verbose: fail verbosely
  *     @classes: resulting classes of attached devices
  *
  *     Reset host port using ATA SRST.  This function is to be used
@@ -2187,7 +2490,7 @@ void ata_std_probeinit(struct ata_port *ap)
  *     RETURNS:
  *     0 on success, -errno otherwise.
  */
-int ata_std_softreset(struct ata_port *ap, int verbose, unsigned int *classes)
+int ata_std_softreset(struct ata_port *ap, unsigned int *classes)
 {
        unsigned int slave_possible = ap->flags & ATA_FLAG_SLAVE_POSS;
        unsigned int devmask = 0, err_mask;
@@ -2195,7 +2498,7 @@ int ata_std_softreset(struct ata_port *ap, int verbose, unsigned int *classes)
 
        DPRINTK("ENTER\n");
 
-       if (ap->ops->scr_read && !sata_dev_present(ap)) {
+       if (ata_port_offline(ap)) {
                classes[0] = ATA_DEV_NONE;
                goto out;
        }
@@ -2213,11 +2516,7 @@ int ata_std_softreset(struct ata_port *ap, int verbose, unsigned int *classes)
        DPRINTK("about to softreset, devmask=%x\n", devmask);
        err_mask = ata_bus_softreset(ap, devmask);
        if (err_mask) {
-               if (verbose)
-                       printk(KERN_ERR "ata%u: SRST failed (err_mask=0x%x)\n",
-                              ap->id, err_mask);
-               else
-                       DPRINTK("EXIT, softreset failed (err_mask=0x%x)\n",
+               ata_port_printk(ap, KERN_ERR, "SRST failed (err_mask=0x%x)\n",
                                err_mask);
                return -EIO;
        }
@@ -2235,7 +2534,6 @@ int ata_std_softreset(struct ata_port *ap, int verbose, unsigned int *classes)
 /**
  *     sata_std_hardreset - reset host port via SATA phy reset
  *     @ap: port to reset
- *     @verbose: fail verbosely
  *     @class: resulting class of attached device
  *
  *     SATA phy-reset host port using DET bits of SControl register.
@@ -2248,35 +2546,57 @@ int ata_std_softreset(struct ata_port *ap, int verbose, unsigned int *classes)
  *     RETURNS:
  *     0 on success, -errno otherwise.
  */
-int sata_std_hardreset(struct ata_port *ap, int verbose, unsigned int *class)
+int sata_std_hardreset(struct ata_port *ap, unsigned int *class)
 {
+       u32 scontrol;
+       int rc;
+
        DPRINTK("ENTER\n");
 
-       /* Issue phy wake/reset */
-       scr_write_flush(ap, SCR_CONTROL, 0x301);
+       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.
+                */
+               if ((rc = sata_scr_read(ap, SCR_CONTROL, &scontrol)))
+                       return rc;
+
+               scontrol = (scontrol & 0x0f0) | 0x302;
 
-       /*
-        * Couldn't find anything in SATA I/II specs, but AHCI-1.1
+               if ((rc = sata_scr_write(ap, SCR_CONTROL, scontrol)))
+                       return rc;
+
+               sata_set_spd(ap);
+       }
+
+       /* issue phy wake/reset */
+       if ((rc = sata_scr_read(ap, SCR_CONTROL, &scontrol)))
+               return rc;
+
+       scontrol = (scontrol & 0x0f0) | 0x301;
+
+       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.
         */
        msleep(1);
 
-       /* Bring phy back */
+       /* bring phy back */
        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)) {
-               if (verbose)
-                       printk(KERN_ERR "ata%u: COMRESET failed "
-                              "(device not ready)\n", ap->id);
-               else
-                       DPRINTK("EXIT, device not ready\n");
+               ata_port_printk(ap, KERN_ERR,
+                               "COMRESET failed (device not ready)\n");
                return -EIO;
        }
 
@@ -2305,19 +2625,23 @@ int sata_std_hardreset(struct ata_port *ap, int verbose, unsigned int *class)
  */
 void ata_std_postreset(struct ata_port *ap, unsigned int *classes)
 {
-       DPRINTK("ENTER\n");
+       u32 serror;
 
-       /* set cable type if it isn't already set */
-       if (ap->cbl == ATA_CBL_NONE && ap->flags & ATA_FLAG_SATA)
-               ap->cbl = ATA_CBL_SATA;
+       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)
@@ -2360,7 +2684,7 @@ int ata_std_probe_reset(struct ata_port *ap, unsigned int *classes)
        ata_reset_fn_t hardreset;
 
        hardreset = NULL;
-       if (ap->flags & ATA_FLAG_SATA && ap->ops->scr_read)
+       if (sata_scr_valid(ap))
                hardreset = sata_std_hardreset;
 
        return ata_drive_probe_reset(ap, ata_std_probeinit,
@@ -2368,16 +2692,15 @@ int ata_std_probe_reset(struct ata_port *ap, unsigned int *classes)
                                     ata_std_postreset, classes);
 }
 
-static int do_probe_reset(struct ata_port *ap, ata_reset_fn_t reset,
-                         ata_postreset_fn_t postreset,
-                         unsigned int *classes)
+int ata_do_reset(struct ata_port *ap, ata_reset_fn_t reset,
+                unsigned int *classes)
 {
        int i, rc;
 
        for (i = 0; i < ATA_MAX_DEVICES; i++)
                classes[i] = ATA_DEV_UNKNOWN;
 
-       rc = reset(ap, 0, classes);
+       rc = reset(ap, classes);
        if (rc)
                return rc;
 
@@ -2394,10 +2717,7 @@ static int do_probe_reset(struct ata_port *ap, ata_reset_fn_t reset,
                        if (classes[i] == ATA_DEV_UNKNOWN)
                                classes[i] = ATA_DEV_NONE;
 
-       if (postreset)
-               postreset(ap, classes);
-
-       return classes[0] != ATA_DEV_UNKNOWN ? 0 : -ENODEV;
+       return 0;
 }
 
 /**
@@ -2421,8 +2741,6 @@ static int do_probe_reset(struct ata_port *ap, ata_reset_fn_t reset,
  *     - If classification is supported, fill classes[] with
  *       recognized class codes.
  *     - If classification is not supported, leave classes[] alone.
- *     - If verbose is non-zero, print error message on failure;
- *       otherwise, shut up.
  *
  *     LOCKING:
  *     Kernel thread context (may sleep)
@@ -2438,31 +2756,63 @@ int ata_drive_probe_reset(struct ata_port *ap, ata_probeinit_fn_t probeinit,
 {
        int rc = -EINVAL;
 
+       ata_eh_freeze_port(ap);
+
        if (probeinit)
                probeinit(ap);
 
-       if (softreset) {
-               rc = do_probe_reset(ap, softreset, postreset, classes);
-               if (rc == 0)
-                       return 0;
+       if (softreset && !sata_set_spd_needed(ap)) {
+               rc = ata_do_reset(ap, softreset, classes);
+               if (rc == 0 && classes[0] != ATA_DEV_UNKNOWN)
+                       goto done;
+               ata_port_printk(ap, KERN_INFO, "softreset failed, "
+                               "will try hardreset in 5 secs\n");
+               ssleep(5);
        }
 
        if (!hardreset)
-               return rc;
+               goto done;
 
-       rc = do_probe_reset(ap, hardreset, postreset, classes);
-       if (rc == 0 || rc != -ENODEV)
-               return rc;
+       while (1) {
+               rc = ata_do_reset(ap, hardreset, classes);
+               if (rc == 0) {
+                       if (classes[0] != ATA_DEV_UNKNOWN)
+                               goto done;
+                       break;
+               }
+
+               if (sata_down_spd_limit(ap))
+                       goto done;
+
+               ata_port_printk(ap, KERN_INFO, "hardreset failed, "
+                               "will retry in 5 secs\n");
+               ssleep(5);
+       }
+
+       if (softreset) {
+               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, classes);
+       }
 
-       if (softreset)
-               rc = do_probe_reset(ap, softreset, postreset, classes);
+ done:
+       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
@@ -2477,17 +2827,16 @@ int ata_drive_probe_reset(struct ata_port *ap, ata_probeinit_fn_t probeinit,
  *     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;
        }
 
@@ -2498,24 +2847,22 @@ static int ata_dev_same_device(struct ata_port *ap, struct ata_device *dev,
        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;
        }
 
@@ -2524,7 +2871,6 @@ static int ata_dev_same_device(struct ata_port *ap, struct ata_device *dev,
 
 /**
  *     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?
  *
@@ -2537,40 +2883,37 @@ static int ata_dev_same_device(struct ata_port *ap, struct ata_device *dev,
  *     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;
-       u16 *id;
+       unsigned int class = dev->class;
+       u16 *id = (void *)dev->ap->sector_buf;
        int rc;
 
-       if (!ata_dev_present(dev))
-               return -ENODEV;
-
-       class = dev->class;
-       id = NULL;
+       if (!ata_dev_enabled(dev)) {
+               rc = -ENODEV;
+               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 */
-       return 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;
 }
 
@@ -2646,7 +2989,6 @@ static int ata_dma_blacklisted(const struct ata_device *dev)
 
 /**
  *     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
@@ -2661,49 +3003,61 @@ static int ata_dma_blacklisted(const struct ata_device *dev)
  *     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;
 
-       xfer_mask = ata_pack_xfermask(ap->pio_mask, ap->mwdma_mask,
-                                     ap->udma_mask);
+       xfer_mask = ata_pack_xfermask(ap->pio_mask,
+                                     ap->mwdma_mask, ap->udma_mask);
+
+       /* Apply cable rule here.  Don't apply it early because when
+        * we handle hot plug the cable type can itself change.
+        */
+       if (ap->cbl == ATA_CBL_PATA40)
+               xfer_mask &= ~(0xF8 << ATA_SHIFT_UDMA);
 
        /* FIXME: Use port-wide xfermask for now */
        for (i = 0; i < ATA_MAX_DEVICES; i++) {
                struct ata_device *d = &ap->device[i];
-               if (!ata_dev_present(d))
+
+               if (ata_dev_absent(d))
+                       continue;
+
+               if (ata_dev_disabled(d)) {
+                       /* to avoid violating device selection timing */
+                       xfer_mask &= ata_pack_xfermask(d->pio_mask,
+                                                      UINT_MAX, UINT_MAX);
                        continue;
-               xfer_mask &= ata_pack_xfermask(d->pio_mask, d->mwdma_mask,
-                                              d->udma_mask);
+               }
+
+               xfer_mask &= ata_pack_xfermask(d->pio_mask,
+                                              d->mwdma_mask, d->udma_mask);
                xfer_mask &= ata_id_xfermask(d->id);
                if (ata_dma_blacklisted(d))
                        xfer_mask &= ~(ATA_MASK_MWDMA | ATA_MASK_UDMA);
-               /* Apply cable rule here. Don't apply it early because when
-                  we handle hot plug the cable type can itself change */
-               if (ap->cbl == ATA_CBL_PATA40)
-                       xfer_mask &= ~(0xF8 << ATA_SHIFT_UDMA);
        }
 
        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)
                        xfer_mask &= ~(ATA_MASK_MWDMA | ATA_MASK_UDMA);
        }
+
        if (ap->ops->mode_filter)
                xfer_mask = ap->ops->mode_filter(ap, dev, xfer_mask);
 
-       ata_unpack_xfermask(xfer_mask, &dev->pio_mask, &dev->mwdma_mask,
-                           &dev->udma_mask);
+       ata_unpack_xfermask(xfer_mask, &dev->pio_mask,
+                           &dev->mwdma_mask, &dev->udma_mask);
 }
 
 /**
  *     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
@@ -2716,8 +3070,7 @@ static void ata_dev_xfermask(struct ata_port *ap, struct ata_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;
@@ -2725,14 +3078,14 @@ static unsigned int ata_dev_set_xfermode(struct ata_port *ap,
        /* 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, 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;
@@ -2740,7 +3093,6 @@ static unsigned int ata_dev_set_xfermode(struct ata_port *ap,
 
 /**
  *     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 (taskfile parameter)
  *     @sectors: Number of sectors (taskfile parameter)
@@ -2751,11 +3103,8 @@ static unsigned int ata_dev_set_xfermode(struct ata_port *ap,
  *     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;
@@ -2767,14 +3116,14 @@ static unsigned int ata_dev_init_params(struct ata_port *ap,
        /* 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, 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;
@@ -2912,6 +3261,15 @@ int ata_check_atapi_dma(struct ata_queued_cmd *qc)
        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;
 }
 /**
@@ -3139,134 +3497,6 @@ skip_map:
        return 0;
 }
 
-/**
- *     ata_poll_qc_complete - turn irq back on and finish qc
- *     @qc: Command to complete
- *     @err_mask: ATA status register content
- *
- *     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);
-       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
- *     @ap: the target ata_port
- *
- *     LOCKING:
- *     None.  (executing in kernel thread context)
- *
- *     RETURNS:
- *     timeout value to use
- */
-
-static unsigned long ata_pio_poll(struct ata_port *ap)
-{
-       struct ata_queued_cmd *qc;
-       u8 status;
-       unsigned int poll_state = HSM_ST_UNKNOWN;
-       unsigned int reg_state = HSM_ST_UNKNOWN;
-
-       qc = ata_qc_from_tag(ap, ap->active_tag);
-       WARN_ON(qc == NULL);
-
-       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
- *     @ap: the target ata_port
- *
- *     LOCKING:
- *     None.  (executing in kernel thread context)
- *
- *     RETURNS:
- *     Non-zero if qc completed, zero otherwise.
- */
-
-static int ata_pio_complete (struct ata_port *ap)
-{
-       struct ata_queued_cmd *qc;
-       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;
-               }
-       }
-
-       qc = ata_qc_from_tag(ap, ap->active_tag);
-       WARN_ON(qc == NULL);
-
-       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
@@ -3435,7 +3665,23 @@ static void ata_pio_sector(struct ata_queued_cmd *qc)
        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++;
@@ -3444,14 +3690,68 @@ static void ata_pio_sector(struct ata_queued_cmd *qc)
                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.
+ */
+
+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);
+
+               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.
+ */
 
-       /* 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 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);
 
-       kunmap(page);
+       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;
+       }
 }
 
 /**
@@ -3492,8 +3792,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);
@@ -3517,7 +3817,23 @@ next_sg:
        /* 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;
@@ -3528,13 +3844,6 @@ next_sg:
                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;
 }
@@ -3556,10 +3865,16 @@ static void atapi_pio_bytes(struct ata_queued_cmd *qc)
        unsigned int ireason, bc_lo, bc_hi, bytes;
        int i_write, do_write = (qc->tf.flags & ATA_TFLAG_WRITE) ? 1 : 0;
 
-       ap->ops->tf_read(ap, &qc->tf);
-       ireason = qc->tf.nsect;
-       bc_lo = qc->tf.lbam;
-       bc_hi = qc->tf.lbah;
+       /* Abuse qc->result_tf for temp storage of intermediate TF
+        * here to save some kernel stack usage.
+        * For normal completion, qc->result_tf is not relevant. For
+        * error, qc->result_tf is later overwritten by ata_qc_complete().
+        * So, the correctness of qc->result_tf is not affected.
+        */
+       ap->ops->tf_read(ap, &qc->result_tf);
+       ireason = qc->result_tf.nsect;
+       bc_lo = qc->result_tf.lbam;
+       bc_hi = qc->result_tf.lbah;
        bytes = (bc_hi << 8) | bc_lo;
 
        /* shall be cleared to zero, indicating xfer of data */
@@ -3571,307 +3886,366 @@ static void atapi_pio_bytes(struct ata_queued_cmd *qc)
        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
+ *     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_port *ap)
+static inline int ata_hsm_ok_in_wq(struct ata_port *ap, struct ata_queued_cmd *qc)
 {
-       struct ata_queued_cmd *qc;
-       u8 status;
-
-       /*
-        * 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 (qc->tf.flags & ATA_TFLAG_POLLING)
+               return 1;
 
-       qc = ata_qc_from_tag(ap, ap->active_tag);
-       WARN_ON(qc == NULL);
+       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;
-               }
-
-               atapi_pio_bytes(qc);
-       } else {
-               /* handle BSY=0, DRQ=0 as error */
-               if ((status & ATA_DRQ) == 0) {
-                       qc->err_mask |= AC_ERR_HSM;
-                       ap->hsm_task_state = HSM_ST_ERR;
-                       return;
-               }
-
-               ata_pio_sector(qc);
-       }
-
-       ata_altstatus(ap); /* flush */
-}
-
-static void ata_pio_error(struct ata_port *ap)
-{
-       struct ata_queued_cmd *qc;
-
-       qc = ata_qc_from_tag(ap, ap->active_tag);
-       WARN_ON(qc == NULL);
-
-       if (qc->tf.command != ATA_CMD_PACKET)
-               printk(KERN_WARNING "ata%u: PIO error\n", ap->id);
-
-       /* 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;
-
-       ata_poll_qc_complete(qc);
+       return 0;
 }
 
-static void ata_pio_task(void *_data)
+/**
+ *     ata_hsm_qc_complete - finish a qc running on standard HSM
+ *     @qc: Command to complete
+ *     @in_wq: 1 if called from workqueue, 0 otherwise
+ *
+ *     Finish @qc which is running on standard HSM.
+ *
+ *     LOCKING:
+ *     If @in_wq is zero, spin_lock_irqsave(host_set lock).
+ *     Otherwise, none on entry and grabs host lock.
+ */
+static void ata_hsm_qc_complete(struct ata_queued_cmd *qc, int in_wq)
 {
-       struct ata_port *ap = _data;
-       unsigned long timeout;
-       int qc_completed;
-
-fsm_start:
-       timeout = 0;
-       qc_completed = 0;
-
-       switch (ap->hsm_task_state) {
-       case HSM_ST_IDLE:
-               return;
-
-       case HSM_ST:
-               ata_pio_block(ap);
-               break;
+       struct ata_port *ap = qc->ap;
+       unsigned long flags;
 
-       case HSM_ST_LAST:
-               qc_completed = ata_pio_complete(ap);
-               break;
+       if (ap->ops->error_handler) {
+               if (in_wq) {
+                       spin_lock_irqsave(&ap->host_set->lock, flags);
 
-       case HSM_ST_POLL:
-       case HSM_ST_LAST_POLL:
-               timeout = ata_pio_poll(ap);
-               break;
+                       /* EH might have kicked in while host_set lock
+                        * is released.
+                        */
+                       qc = ata_qc_from_tag(ap, qc->tag);
+                       if (qc) {
+                               if (likely(!(qc->err_mask & AC_ERR_HSM))) {
+                                       ata_irq_on(ap);
+                                       ata_qc_complete(qc);
+                               } else
+                                       ata_port_freeze(ap);
+                       }
 
-       case HSM_ST_TMOUT:
-       case HSM_ST_ERR:
-               ata_pio_error(ap);
-               return;
+                       spin_unlock_irqrestore(&ap->host_set->lock, flags);
+               } else {
+                       if (likely(!(qc->err_mask & AC_ERR_HSM)))
+                               ata_qc_complete(qc);
+                       else
+                               ata_port_freeze(ap);
+               }
+       } else {
+               if (in_wq) {
+                       spin_lock_irqsave(&ap->host_set->lock, flags);
+                       ata_irq_on(ap);
+                       ata_qc_complete(qc);
+                       spin_unlock_irqrestore(&ap->host_set->lock, flags);
+               } else
+                       ata_qc_complete(qc);
        }
 
-       if (timeout)
-               ata_port_queue_task(ap, ata_pio_task, ap, timeout);
-       else if (!qc_completed)
-               goto fsm_start;
+       ata_altstatus(ap); /* flush */
 }
 
 /**
- *     atapi_packet_task - Write CDB bytes to hardware
- *     @_data: Port to which ATAPI device is attached.
- *
- *     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.
+ *     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
  *
- *     LOCKING:
- *     Kernel thread context (may sleep)
+ *     RETURNS:
+ *     1 when poll next status needed, 0 otherwise.
  */
 
-static void atapi_packet_task(void *_data)
+static int ata_hsm_move(struct ata_port *ap, struct ata_queued_cmd *qc,
+                        u8 status, int in_wq)
 {
-       struct ata_port *ap = _data;
-       struct ata_queued_cmd *qc;
-       u8 status;
+       unsigned long flags = 0;
+       int poll_next;
 
-       qc = ata_qc_from_tag(ap, ap->active_tag);
-       WARN_ON(qc == NULL);
-       WARN_ON(!(qc->flags & ATA_QCFLAG_ACTIVE));
+       WARN_ON((qc->flags & ATA_QCFLAG_ACTIVE) == 0);
 
-       /* 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 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));
 
-       /* 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;
-       }
+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);
 
-       /* send SCSI cdb */
-       DPRINTK("send cdb\n");
-       WARN_ON(qc->dev->cdb_len < 12);
+       switch (ap->hsm_task_state) {
+       case HSM_ST_FIRST:
+               /* Send first data block or PACKET CDB */
 
-       if (qc->tf.protocol == ATA_PROT_ATAPI_DMA ||
-           qc->tf.protocol == ATA_PROT_ATAPI_NODATA) {
-               unsigned long flags;
+               /* 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_DRQ) == 0)) {
+                       /* handle BSY=0, DRQ=0 as error */
+                       if (likely(status & (ATA_ERR | ATA_DF)))
+                               /* device stops HSM for abort/error */
+                               qc->err_mask |= AC_ERR_DEV;
+                       else
+                               /* HSM violation. Let EH handle this */
+                               qc->err_mask |= AC_ERR_HSM;
 
-               /* 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.
+                       ap->hsm_task_state = HSM_ST_ERR;
+                       goto fsm_start;
+               }
+
+               /* 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.
                 */
-               spin_lock_irqsave(&ap->host_set->lock, flags);
-               ap->flags &= ~ATA_FLAG_NOINTR;
-               ata_data_xfer(ap, qc->cdb, qc->dev->cdb_len, 1);
-               ata_altstatus(ap); /* flush */
+               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_HSM;
+                       ap->hsm_task_state = HSM_ST_ERR;
+                       goto fsm_start;
+               }
 
-               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);
-               ata_altstatus(ap); /* flush */
+               /* 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);
 
-               /* PIO commands are handled by polling */
-               ap->hsm_task_state = HSM_ST;
-               ata_port_queue_task(ap, ata_pio_task, ap, 0);
-       }
+               if (qc->tf.protocol == ATA_PROT_PIO) {
+                       /* PIO data out protocol.
+                        * send first data block.
+                        */
 
-       return;
+                       /* 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;
 
-err_out:
-       ata_poll_qc_complete(qc);
-}
+       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 or device error.
+                                * Device error will be tagged in HSM_ST_LAST.
+                                */
+                               ap->hsm_task_state = HSM_ST_LAST;
+                               goto fsm_start;
+                       }
 
-/**
- *     ata_qc_timeout - Handle timeout of queued command
- *     @qc: Command that timed out
- *
- *     Some part of the kernel (currently, only the SCSI layer)
- *     has noticed that the active command on port @ap has not
- *     completed after a specified length of time.  Handle this
- *     condition by disabling DMA (if necessary) and completing
- *     transactions, with error if necessary.
- *
- *     This also handles the case of the "lost interrupt", where
- *     for some reason (possibly hardware bug, possibly driver bug)
- *     an interrupt was not delivered to the driver, even though the
- *     transaction completed successfully.
- *
- *     LOCKING:
- *     Inherited from SCSI layer (none, can sleep)
- */
+                       /* 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_HSM;
+                               ap->hsm_task_state = HSM_ST_ERR;
+                               goto fsm_start;
+                       }
 
-static void ata_qc_timeout(struct ata_queued_cmd *qc)
-{
-       struct ata_port *ap = qc->ap;
-       struct ata_host_set *host_set = ap->host_set;
-       u8 host_stat = 0, drv_stat;
-       unsigned long flags;
+                       atapi_pio_bytes(qc);
 
-       DPRINTK("ENTER\n");
+                       if (unlikely(ap->hsm_task_state == HSM_ST_ERR))
+                               /* bad ireason reported by device */
+                               goto fsm_start;
 
-       ap->hsm_task_state = HSM_ST_IDLE;
+               } else {
+                       /* ATA PIO protocol */
+                       if (unlikely((status & ATA_DRQ) == 0)) {
+                               /* handle BSY=0, DRQ=0 as error */
+                               if (likely(status & (ATA_ERR | ATA_DF)))
+                                       /* device stops HSM for abort/error */
+                                       qc->err_mask |= AC_ERR_DEV;
+                               else
+                                       /* HSM violation. Let EH handle this */
+                                       qc->err_mask |= AC_ERR_HSM;
+
+                               ap->hsm_task_state = HSM_ST_ERR;
+                               goto fsm_start;
+                       }
 
-       spin_lock_irqsave(&host_set->lock, flags);
+                       /* 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);
+                               }
+
+                               if (status & (ATA_BUSY | ATA_DRQ))
+                                       qc->err_mask |= AC_ERR_HSM;
+
+                               /* 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;
+                       }
 
-       switch (qc->tf.protocol) {
+                       ata_pio_sectors(qc);
 
-       case ATA_PROT_DMA:
-       case ATA_PROT_ATAPI_DMA:
-               host_stat = ap->ops->bmdma_status(ap);
+                       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;
+                       }
+               }
 
-               /* before we do anything else, clear DMA-Start bit */
-               ap->ops->bmdma_stop(qc);
+               ata_altstatus(ap); /* flush */
+               poll_next = 1;
+               break;
 
-               /* fall through */
+       case HSM_ST_LAST:
+               if (unlikely(!ata_ok(status))) {
+                       qc->err_mask |= __ac_err_mask(status);
+                       ap->hsm_task_state = HSM_ST_ERR;
+                       goto fsm_start;
+               }
 
-       default:
-               ata_altstatus(ap);
-               drv_stat = ata_chk_status(ap);
+               /* no more data to transfer */
+               DPRINTK("ata%u: dev %u command complete, drv_stat 0x%x\n",
+                       ap->id, qc->dev->devno, status);
 
-               /* ack bmdma irq events */
-               ap->ops->irq_clear(ap);
+               WARN_ON(qc->err_mask);
 
-               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);
+               ap->hsm_task_state = HSM_ST_IDLE;
 
                /* complete taskfile transaction */
-               qc->err_mask |= ac_err_mask(drv_stat);
+               ata_hsm_qc_complete(qc, in_wq);
+
+               poll_next = 0;
                break;
-       }
 
-       spin_unlock_irqrestore(&host_set->lock, flags);
+       case HSM_ST_ERR:
+               /* make sure qc->err_mask is available to
+                * know what's wrong and recover
+                */
+               WARN_ON(qc->err_mask == 0);
 
-       ata_eh_qc_complete(qc);
+               ap->hsm_task_state = HSM_ST_IDLE;
 
-       DPRINTK("EXIT\n");
-}
+               /* complete taskfile transaction */
+               ata_hsm_qc_complete(qc, in_wq);
 
-/**
- *     ata_eng_timeout - Handle timeout of queued command
- *     @ap: Port on which timed-out command is active
- *
- *     Some part of the kernel (currently, only the SCSI layer)
- *     has noticed that the active command on port @ap has not
- *     completed after a specified length of time.  Handle this
- *     condition by disabling DMA (if necessary) and completing
- *     transactions, with error if necessary.
- *
- *     This also handles the case of the "lost interrupt", where
- *     for some reason (possibly hardware bug, possibly driver bug)
- *     an interrupt was not delivered to the driver, even though the
- *     transaction completed successfully.
- *
- *     LOCKING:
- *     Inherited from SCSI layer (none, can sleep)
- */
+               poll_next = 0;
+               break;
+       default:
+               poll_next = 0;
+               BUG();
+       }
+
+       return poll_next;
+}
 
-void ata_eng_timeout(struct ata_port *ap)
+static void ata_pio_task(void *_data)
 {
-       DPRINTK("ENTER\n");
+       struct ata_queued_cmd *qc = _data;
+       struct ata_port *ap = qc->ap;
+       u8 status;
+       int poll_next;
 
-       ata_qc_timeout(ata_qc_from_tag(ap, ap->active_tag));
+fsm_start:
+       WARN_ON(ap->hsm_task_state == HSM_ST_IDLE);
 
-       DPRINTK("EXIT\n");
+       /*
+        * 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;
+               }
+       }
+
+       /* move the HSM */
+       poll_next = ata_hsm_move(ap, qc, status, 1);
+
+       /* another command or interrupt handler
+        * may be running at this point.
+        */
+       if (poll_next)
+               goto fsm_start;
 }
 
 /**
@@ -3888,9 +4262,14 @@ static struct ata_queued_cmd *ata_qc_new(struct ata_port *ap)
        struct ata_queued_cmd *qc = NULL;
        unsigned int i;
 
-       for (i = 0; i < ATA_MAX_QUEUE; i++)
-               if (!test_and_set_bit(i, &ap->qactive)) {
-                       qc = ata_qc_from_tag(ap, 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->qc_allocated)) {
+                       qc = __ata_qc_from_tag(ap, i);
                        break;
                }
 
@@ -3902,16 +4281,15 @@ static struct ata_queued_cmd *ata_qc_new(struct ata_port *ap)
 
 /**
  *     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);
@@ -3946,36 +4324,153 @@ void ata_qc_free(struct ata_queued_cmd *qc)
        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);
+               clear_bit(tag, &ap->qc_allocated);
        }
 }
 
 void __ata_qc_complete(struct ata_queued_cmd *qc)
 {
+       struct ata_port *ap = qc->ap;
+
        WARN_ON(qc == NULL);    /* ata_qc_from_tag _might_ return NULL */
        WARN_ON(!(qc->flags & ATA_QCFLAG_ACTIVE));
 
        if (likely(qc->flags & ATA_QCFLAG_DMAMAP))
                ata_sg_clean(qc);
 
+       /* command should be marked inactive atomically with qc completion */
+       if (qc->tf.protocol == ATA_PROT_NCQ)
+               ap->sactive &= ~(1 << qc->tag);
+       else
+               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->flags &= ~ATA_QCFLAG_ACTIVE;
+       ap->qc_active &= ~(1 << qc->tag);
 
        /* call completion callback */
        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);
+       }
+}
+
+/**
+ *     ata_qc_complete_multiple - Complete multiple qcs successfully
+ *     @ap: port in question
+ *     @qc_active: new qc_active mask
+ *     @finish_qc: LLDD callback invoked before completing a qc
+ *
+ *     Complete in-flight commands.  This functions is meant to be
+ *     called from low-level driver's interrupt routine to complete
+ *     requests normally.  ap->qc_active and @qc_active is compared
+ *     and commands are completed accordingly.
+ *
+ *     LOCKING:
+ *     spin_lock_irqsave(host_set lock)
+ *
+ *     RETURNS:
+ *     Number of completed commands on success, -errno otherwise.
+ */
+int ata_qc_complete_multiple(struct ata_port *ap, u32 qc_active,
+                            void (*finish_qc)(struct ata_queued_cmd *))
+{
+       int nr_done = 0;
+       u32 done_mask;
+       int i;
+
+       done_mask = ap->qc_active ^ qc_active;
+
+       if (unlikely(done_mask & qc_active)) {
+               ata_port_printk(ap, KERN_ERR, "illegal qc_active transition "
+                               "(%08x->%08x)\n", ap->qc_active, qc_active);
+               return -EINVAL;
+       }
+
+       for (i = 0; i < ATA_MAX_QUEUE; i++) {
+               struct ata_queued_cmd *qc;
+
+               if (!(done_mask & (1 << i)))
+                       continue;
+
+               if ((qc = ata_qc_from_tag(ap, i))) {
+                       if (finish_qc)
+                               finish_qc(qc);
+                       ata_qc_complete(qc);
+                       nr_done++;
+               }
+       }
+
+       return nr_done;
+}
+
 static inline int ata_should_dma_map(struct ata_queued_cmd *qc)
 {
        struct ata_port *ap = qc->ap;
 
        switch (qc->tf.protocol) {
+       case ATA_PROT_NCQ:
        case ATA_PROT_DMA:
        case ATA_PROT_ATAPI_DMA:
                return 1;
@@ -4010,8 +4505,22 @@ void ata_qc_issue(struct ata_queued_cmd *qc)
 {
        struct ata_port *ap = qc->ap;
 
-       qc->ap->active_tag = qc->tag;
+       /* Make sure only one non-NCQ command is outstanding.  The
+        * check is skipped for old EH because it reuses active qc to
+        * request ATAPI sense.
+        */
+       WARN_ON(ap->ops->error_handler && ata_tag_valid(ap->active_tag));
+
+       if (qc->tf.protocol == ATA_PROT_NCQ) {
+               WARN_ON(ap->sactive & (1 << qc->tag));
+               ap->sactive |= 1 << qc->tag;
+       } else {
+               WARN_ON(ap->sactive);
+               ap->active_tag = qc->tag;
+       }
+
        qc->flags |= ATA_QCFLAG_ACTIVE;
+       ap->qc_active |= 1 << qc->tag;
 
        if (ata_should_dma_map(qc)) {
                if (qc->flags & ATA_QCFLAG_SG) {
@@ -4061,43 +4570,105 @@ unsigned int ata_qc_issue_prot(struct ata_queued_cmd *qc)
 {
        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, ap, 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, ap, 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, ap, 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, ap, 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:
@@ -4127,52 +4698,66 @@ unsigned int ata_qc_issue_prot(struct ata_queued_cmd *qc)
 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);
-
-               /* if it's not our irq... */
-               if (!(host_stat & ATA_DMA_INTR))
-                       goto idle_irq;
+       u8 status, host_stat = 0;
 
-               /* 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:
@@ -4181,7 +4766,7 @@ 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
@@ -4219,11 +4804,11 @@ irqreturn_t ata_interrupt (int irq, void *dev_instance, struct pt_regs *regs)
 
                ap = host_set->ports[i];
                if (ap &&
-                   !(ap->flags & (ATA_FLAG_PORT_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);
                }
@@ -4234,32 +4819,168 @@ irqreturn_t ata_interrupt (int irq, void *dev_instance, struct pt_regs *regs)
        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, 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;
 
@@ -4271,22 +4992,21 @@ static int ata_flush_cache(struct ata_port *ap, struct ata_device *dev)
        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
@@ -4294,38 +5014,43 @@ static int ata_start_drive(struct ata_port *ap, struct ata_device *dev)
  *     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;
-               ata_set_mode(ap);
+               while (ata_set_mode(ap, &failed_dev))
+                       ata_dev_disable(failed_dev);
        }
-       if (!ata_dev_present(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
  *     @state: target power management state
  *
  *     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)
 {
-       if (!ata_dev_present(dev))
+       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;
 }
@@ -4439,7 +5164,7 @@ static void ata_host_init(struct ata_port *ap, struct Scsi_Host *host,
        host->unique_id = ata_unique_id++;
        host->max_cmd_len = 12;
 
-       ap->flags = ATA_FLAG_PORT_DISABLED;
+       ap->flags = ATA_FLAG_DISABLED;
        ap->id = host->unique_id;
        ap->host = host;
        ap->ctl = ATA_DEVCTL_OBS;
@@ -4453,15 +5178,21 @@ static void ata_host_init(struct ata_port *ap, struct Scsi_Host *host,
        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;
@@ -4514,7 +5245,7 @@ static struct ata_port * ata_host_add(const struct ata_probe_ent *ent,
 
        host->transportt = &ata_scsi_transport_template;
 
-       ap = (struct ata_port *) &host->hostdata[0];
+       ap = ata_shost_to_port(host);
 
        ata_host_init(ap, host, host_set, ent, port_no);
 
@@ -4585,18 +5316,18 @@ int ata_device_add(const struct ata_probe_ent *ent)
                                (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++;
        }
 
@@ -4631,8 +5362,7 @@ int ata_device_add(const struct ata_probe_ent *ent)
 
                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,
@@ -4727,15 +5457,12 @@ void ata_host_set_remove(struct ata_host_set *host_set)
 
 int ata_scsi_release(struct Scsi_Host *host)
 {
-       struct ata_port *ap = (struct ata_port *) &host->hostdata[0];
-       int i;
+       struct ata_port *ap = ata_shost_to_port(host);
 
        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;
@@ -4894,6 +5621,52 @@ int ata_ratelimit(void)
        return rc;
 }
 
+/**
+ *     ata_wait_register - wait until register value changes
+ *     @reg: IO-mapped register
+ *     @mask: Mask to apply to read register value
+ *     @val: Wait condition
+ *     @interval_msec: polling interval in milliseconds
+ *     @timeout_msec: timeout in milliseconds
+ *
+ *     Waiting for some bits of register to change is a common
+ *     operation for ATA controllers.  This function reads 32bit LE
+ *     IO-mapped register @reg and tests for the following condition.
+ *
+ *     (*@reg & mask) != val
+ *
+ *     If the condition is met, it returns; otherwise, the process is
+ *     repeated after @interval_msec until timeout.
+ *
+ *     LOCKING:
+ *     Kernel thread context (may sleep)
+ *
+ *     RETURNS:
+ *     The final register value.
+ */
+u32 ata_wait_register(void __iomem *reg, u32 mask, u32 val,
+                     unsigned long interval_msec,
+                     unsigned long timeout_msec)
+{
+       unsigned long timeout;
+       u32 tmp;
+
+       tmp = ioread32(reg);
+
+       /* Calculate timeout _after_ the first read to make sure
+        * preceding writes reach the controller before starting to
+        * eat away the timeout.
+        */
+       timeout = jiffies + (timeout_msec * HZ) / 1000;
+
+       while ((tmp & mask) == val && time_before(jiffies, timeout)) {
+               msleep(interval_msec);
+               tmp = ioread32(reg);
+       }
+
+       return tmp;
+}
+
 /*
  * libata is essentially a library of internal helper functions for
  * low-level ATA host controller drivers.  As such, the API/ABI is
@@ -4907,9 +5680,9 @@ 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_complete_multiple);
 EXPORT_SYMBOL_GPL(ata_qc_issue_prot);
-EXPORT_SYMBOL_GPL(ata_eng_timeout);
 EXPORT_SYMBOL_GPL(ata_tf_load);
 EXPORT_SYMBOL_GPL(ata_tf_read);
 EXPORT_SYMBOL_GPL(ata_noop_dev_select);
@@ -4930,7 +5703,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(sata_set_spd);
 EXPORT_SYMBOL_GPL(sata_phy_reset);
 EXPORT_SYMBOL_GPL(__sata_phy_reset);
 EXPORT_SYMBOL_GPL(ata_bus_reset);
@@ -4945,18 +5724,24 @@ EXPORT_SYMBOL_GPL(ata_dev_classify);
 EXPORT_SYMBOL_GPL(ata_dev_pair);
 EXPORT_SYMBOL_GPL(ata_port_disable);
 EXPORT_SYMBOL_GPL(ata_ratelimit);
+EXPORT_SYMBOL_GPL(ata_wait_register);
 EXPORT_SYMBOL_GPL(ata_busy_sleep);
 EXPORT_SYMBOL_GPL(ata_port_queue_task);
 EXPORT_SYMBOL_GPL(ata_scsi_ioctl);
 EXPORT_SYMBOL_GPL(ata_scsi_queuecmd);
 EXPORT_SYMBOL_GPL(ata_scsi_slave_config);
+EXPORT_SYMBOL_GPL(ata_scsi_change_queue_depth);
 EXPORT_SYMBOL_GPL(ata_scsi_release);
 EXPORT_SYMBOL_GPL(ata_host_intr);
+EXPORT_SYMBOL_GPL(sata_scr_valid);
+EXPORT_SYMBOL_GPL(sata_scr_read);
+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);
-EXPORT_SYMBOL_GPL(ata_eh_qc_complete);
-EXPORT_SYMBOL_GPL(ata_eh_qc_retry);
 
 EXPORT_SYMBOL_GPL(ata_pio_need_iordy);
 EXPORT_SYMBOL_GPL(ata_timing_compute);
@@ -4978,3 +5763,13 @@ EXPORT_SYMBOL_GPL(ata_device_suspend);
 EXPORT_SYMBOL_GPL(ata_device_resume);
 EXPORT_SYMBOL_GPL(ata_scsi_device_suspend);
 EXPORT_SYMBOL_GPL(ata_scsi_device_resume);
+
+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 --git a/drivers/scsi/libata-eh.c b/drivers/scsi/libata-eh.c
new file mode 100644 (file)
index 0000000..71b45ad
--- /dev/null
@@ -0,0 +1,1561 @@
+/*
+ *  libata-eh.c - libata error handling
+ *
+ *  Maintained by:  Jeff Garzik <jgarzik@pobox.com>
+ *                 Please ALWAYS copy linux-ide@vger.kernel.org
+ *                 on emails.
+ *
+ *  Copyright 2006 Tejun Heo <htejun@gmail.com>
+ *
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public License as
+ *  published by the Free Software Foundation; either version 2, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; see the file COPYING.  If not, write to
+ *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139,
+ *  USA.
+ *
+ *
+ *  libata documentation is available via 'make {ps|pdf}docs',
+ *  as Documentation/DocBook/libata.*
+ *
+ *  Hardware documentation available from http://www.t13.org/ and
+ *  http://www.sata-io.org/
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <scsi/scsi.h>
+#include <scsi/scsi_host.h>
+#include <scsi/scsi_eh.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_cmnd.h>
+#include "scsi_transport_api.h"
+
+#include <linux/libata.h>
+
+#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
+ *
+ *     Handles SCSI layer timeout.  We race with normal completion of
+ *     the qc for @cmd.  If the qc is already gone, we lose and let
+ *     the scsi command finish (EH_HANDLED).  Otherwise, the qc has
+ *     timed out and EH should be invoked.  Prevent ata_qc_complete()
+ *     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
+ *
+ *     RETURNS:
+ *     EH_HANDLED or EH_NOT_HANDLED
+ */
+enum scsi_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd)
+{
+       struct Scsi_Host *host = cmd->device->host;
+       struct ata_port *ap = ata_shost_to_port(host);
+       unsigned long flags;
+       struct ata_queued_cmd *qc;
+       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) {
+               WARN_ON(qc->scsicmd != cmd);
+               qc->flags |= ATA_QCFLAG_EH_SCHEDULED;
+               qc->err_mask |= AC_ERR_TIMEOUT;
+               ret = EH_NOT_HANDLED;
+       }
+       spin_unlock_irqrestore(&ap->host_set->lock, flags);
+
+ out:
+       DPRINTK("EXIT, ret=%d\n", ret);
+       return ret;
+}
+
+/**
+ *     ata_scsi_error - SCSI layer error handler callback
+ *     @host: SCSI host on which error occurred
+ *
+ *     Handles SCSI-layer-thrown error events.
+ *
+ *     LOCKING:
+ *     Inherited from SCSI layer (none, can sleep)
+ *
+ *     RETURNS:
+ *     Zero.
+ */
+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 port task */
+       ata_port_flush_task(ap);
+
+       /* 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);
+                       }
+               }
+
+               /* 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");
+}
+
+/**
+ *     ata_qc_timeout - Handle timeout of queued command
+ *     @qc: Command that timed out
+ *
+ *     Some part of the kernel (currently, only the SCSI layer)
+ *     has noticed that the active command on port @ap has not
+ *     completed after a specified length of time.  Handle this
+ *     condition by disabling DMA (if necessary) and completing
+ *     transactions, with error if necessary.
+ *
+ *     This also handles the case of the "lost interrupt", where
+ *     for some reason (possibly hardware bug, possibly driver bug)
+ *     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)
+ */
+static void ata_qc_timeout(struct ata_queued_cmd *qc)
+{
+       struct ata_port *ap = qc->ap;
+       struct ata_host_set *host_set = ap->host_set;
+       u8 host_stat = 0, drv_stat;
+       unsigned long flags;
+
+       DPRINTK("ENTER\n");
+
+       ap->hsm_task_state = HSM_ST_IDLE;
+
+       spin_lock_irqsave(&host_set->lock, flags);
+
+       switch (qc->tf.protocol) {
+
+       case ATA_PROT_DMA:
+       case ATA_PROT_ATAPI_DMA:
+               host_stat = ap->ops->bmdma_status(ap);
+
+               /* before we do anything else, clear DMA-Start bit */
+               ap->ops->bmdma_stop(qc);
+
+               /* fall through */
+
+       default:
+               ata_altstatus(ap);
+               drv_stat = ata_chk_status(ap);
+
+               /* ack bmdma irq events */
+               ap->ops->irq_clear(ap);
+
+               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_TIMEOUT;
+               break;
+       }
+
+       spin_unlock_irqrestore(&host_set->lock, flags);
+
+       ata_eh_qc_complete(qc);
+
+       DPRINTK("EXIT\n");
+}
+
+/**
+ *     ata_eng_timeout - Handle timeout of queued command
+ *     @ap: Port on which timed-out command is active
+ *
+ *     Some part of the kernel (currently, only the SCSI layer)
+ *     has noticed that the active command on port @ap has not
+ *     completed after a specified length of time.  Handle this
+ *     condition by disabling DMA (if necessary) and completing
+ *     transactions, with error if necessary.
+ *
+ *     This also handles the case of the "lost interrupt", where
+ *     for some reason (possibly hardware bug, possibly driver bug)
+ *     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)
+ */
+void ata_eng_timeout(struct ata_port *ap)
+{
+       DPRINTK("ENTER\n");
+
+       ata_qc_timeout(ata_qc_from_tag(ap, ap->active_tag));
+
+       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;
+       scsi_schedule_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 */
+}
+
+static void __ata_eh_qc_complete(struct ata_queued_cmd *qc)
+{
+       struct ata_port *ap = qc->ap;
+       struct scsi_cmnd *scmd = qc->scsicmd;
+       unsigned long flags;
+
+       spin_lock_irqsave(&ap->host_set->lock, flags);
+       qc->scsidone = ata_eh_scsidone;
+       __ata_qc_complete(qc);
+       WARN_ON(ata_tag_valid(qc->tag));
+       spin_unlock_irqrestore(&ap->host_set->lock, flags);
+
+       scsi_eh_finish_cmd(scmd, &ap->eh_done_q);
+}
+
+/**
+ *     ata_eh_qc_complete - Complete an active ATA command from EH
+ *     @qc: Command to complete
+ *
+ *     Indicate to the mid and upper layers that an ATA command has
+ *     completed.  To be used from EH.
+ */
+void ata_eh_qc_complete(struct ata_queued_cmd *qc)
+{
+       struct scsi_cmnd *scmd = qc->scsicmd;
+       scmd->retries = scmd->allowed;
+       __ata_eh_qc_complete(qc);
+}
+
+/**
+ *     ata_eh_qc_retry - Tell midlayer to retry an ATA command after EH
+ *     @qc: Command to retry
+ *
+ *     Indicate to the mid and upper layers that an ATA command
+ *     should be retried.  To be used from EH.
+ *
+ *     SCSI midlayer limits the number of retries to scmd->allowed.
+ *     scmd->retries is decremented for commands which get retried
+ *     due to unrelated failures (qc->err_mask is zero).
+ */
+void ata_eh_qc_retry(struct ata_queued_cmd *qc)
+{
+       struct scsi_cmnd *scmd = qc->scsicmd;
+       if (!qc->err_mask && scmd->retries)
+               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";
+}
+
+/**
+ *     ata_read_log_page - read a specific log page
+ *     @dev: target device
+ *     @page: page to read
+ *     @buf: buffer to store read page
+ *     @sectors: number of sectors to read
+ *
+ *     Read log page using READ_LOG_EXT command.
+ *
+ *     LOCKING:
+ *     Kernel thread context (may sleep).
+ *
+ *     RETURNS:
+ *     0 on success, AC_ERR_* mask otherwise.
+ */
+static unsigned int ata_read_log_page(struct ata_device *dev,
+                                     u8 page, void *buf, unsigned int sectors)
+{
+       struct ata_taskfile tf;
+       unsigned int err_mask;
+
+       DPRINTK("read log page - page %d\n", page);
+
+       ata_tf_init(dev, &tf);
+       tf.command = ATA_CMD_READ_LOG_EXT;
+       tf.lbal = page;
+       tf.nsect = sectors;
+       tf.hob_nsect = sectors >> 8;
+       tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_LBA48 | ATA_TFLAG_DEVICE;
+       tf.protocol = ATA_PROT_PIO;
+
+       err_mask = ata_exec_internal(dev, &tf, NULL, DMA_FROM_DEVICE,
+                                    buf, sectors * ATA_SECT_SIZE);
+
+       DPRINTK("EXIT, err_mask=%x\n", err_mask);
+       return err_mask;
+}
+
+/**
+ *     ata_eh_read_log_10h - Read log page 10h for NCQ error details
+ *     @dev: Device to read log page 10h from
+ *     @tag: Resulting tag of the failed command
+ *     @tf: Resulting taskfile registers of the failed command
+ *
+ *     Read log page 10h to obtain NCQ error details and clear error
+ *     condition.
+ *
+ *     LOCKING:
+ *     Kernel thread context (may sleep).
+ *
+ *     RETURNS:
+ *     0 on success, -errno otherwise.
+ */
+static int ata_eh_read_log_10h(struct ata_device *dev,
+                              int *tag, struct ata_taskfile *tf)
+{
+       u8 *buf = dev->ap->sector_buf;
+       unsigned int err_mask;
+       u8 csum;
+       int i;
+
+       err_mask = ata_read_log_page(dev, ATA_LOG_SATA_NCQ, buf, 1);
+       if (err_mask)
+               return -EIO;
+
+       csum = 0;
+       for (i = 0; i < ATA_SECT_SIZE; i++)
+               csum += buf[i];
+       if (csum)
+               ata_dev_printk(dev, KERN_WARNING,
+                              "invalid checksum 0x%x on log page 10h\n", csum);
+
+       if (buf[0] & 0x80)
+               return -ENOENT;
+
+       *tag = buf[0] & 0x1f;
+
+       tf->command = buf[2];
+       tf->feature = buf[3];
+       tf->lbal = buf[4];
+       tf->lbam = buf[5];
+       tf->lbah = buf[6];
+       tf->device = buf[7];
+       tf->hob_lbal = buf[8];
+       tf->hob_lbam = buf[9];
+       tf->hob_lbah = buf[10];
+       tf->nsect = buf[12];
+       tf->hob_nsect = buf[13];
+
+       return 0;
+}
+
+/**
+ *     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_ncq_error - analyze NCQ error
+ *     @ap: ATA port to analyze NCQ error for
+ *
+ *     Read log page 10h, determine the offending qc and acquire
+ *     error status TF.  For NCQ device errors, all LLDDs have to do
+ *     is setting AC_ERR_DEV in ehi->err_mask.  This function takes
+ *     care of the rest.
+ *
+ *     LOCKING:
+ *     Kernel thread context (may sleep).
+ */
+static void ata_eh_analyze_ncq_error(struct ata_port *ap)
+{
+       struct ata_eh_context *ehc = &ap->eh_context;
+       struct ata_device *dev = ap->device;
+       struct ata_queued_cmd *qc;
+       struct ata_taskfile tf;
+       int tag, rc;
+
+       /* if frozen, we can't do much */
+       if (ap->flags & ATA_FLAG_FROZEN)
+               return;
+
+       /* is it NCQ device error? */
+       if (!ap->sactive || !(ehc->i.err_mask & AC_ERR_DEV))
+               return;
+
+       /* has LLDD analyzed already? */
+       for (tag = 0; tag < ATA_MAX_QUEUE; tag++) {
+               qc = __ata_qc_from_tag(ap, tag);
+
+               if (!(qc->flags & ATA_QCFLAG_FAILED))
+                       continue;
+
+               if (qc->err_mask)
+                       return;
+       }
+
+       /* okay, this error is ours */
+       rc = ata_eh_read_log_10h(dev, &tag, &tf);
+       if (rc) {
+               ata_port_printk(ap, KERN_ERR, "failed to read log page 10h "
+                               "(errno=%d)\n", rc);
+               return;
+       }
+
+       if (!(ap->sactive & (1 << tag))) {
+               ata_port_printk(ap, KERN_ERR, "log page 10h reported "
+                               "inactive tag %d\n", tag);
+               return;
+       }
+
+       /* we've got the perpetrator, condemn it */
+       qc = __ata_qc_from_tag(ap, tag);
+       memcpy(&qc->result_tf, &tf, sizeof(tf));
+       qc->err_mask |= AC_ERR_DEV;
+       ehc->i.err_mask &= ~AC_ERR_DEV;
+}
+
+/**
+ *     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;
+
+       /* analyze NCQ failure */
+       ata_eh_analyze_ncq_error(ap);
+
+       /* 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;
+
+               /* 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);
+
+       /* enforce default EH actions */
+       if (ap->flags & ATA_FLAG_FROZEN ||
+           all_err_mask & (AC_ERR_HSM | AC_ERR_TIMEOUT))
+               action |= ATA_EH_SOFTRESET;
+       else if (all_err_mask)
+               action |= ATA_EH_REVALIDATE;
+
+       /* record autopsy result */
+       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 "
+                              "SAct 0x%x SErr 0x%x action 0x%x%s\n",
+                              ehc->i.err_mask, ap->sactive, 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 "
+                               "SAct 0x%x SErr 0x%x action 0x%x%s\n",
+                               ehc->i.err_mask, ap->sactive, 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);
+}
index a0289ec..2007b4b 100644 (file)
@@ -41,6 +41,7 @@
 #include <scsi/scsi_eh.h>
 #include <scsi/scsi_device.h>
 #include <scsi/scsi_request.h>
+#include <scsi/scsi_tcq.h>
 #include <scsi/scsi_transport.h>
 #include <linux/libata.h>
 #include <linux/hdreg.h>
@@ -53,8 +54,6 @@
 typedef unsigned int (*ata_xlat_func_t)(struct ata_queued_cmd *qc, const u8 *scsicmd);
 static struct ata_device *
 ata_scsi_find_dev(struct ata_port *ap, const struct scsi_device *scsidev);
-static void ata_scsi_error(struct Scsi_Host *host);
-enum scsi_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd);
 
 #define RW_RECOVERY_MPAGE 0x1
 #define RW_RECOVERY_MPAGE_LEN 12
@@ -304,7 +303,6 @@ int ata_scsi_ioctl(struct scsi_device *scsidev, int cmd, void __user *arg)
 
 /**
  *     ata_scsi_qc_new - acquire new ata_queued_cmd reference
- *     @ap: ATA port to which the new command is attached
  *     @dev: ATA device to which the new command is attached
  *     @cmd: SCSI command that originated this ATA command
  *     @done: SCSI command completion function
@@ -323,14 +321,13 @@ int ata_scsi_ioctl(struct scsi_device *scsidev, int cmd, void __user *arg)
  *     RETURNS:
  *     Command allocated, or %NULL if none available.
  */
-struct ata_queued_cmd *ata_scsi_qc_new(struct ata_port *ap,
-                                      struct ata_device *dev,
+struct ata_queued_cmd *ata_scsi_qc_new(struct ata_device *dev,
                                       struct scsi_cmnd *cmd,
                                       void (*done)(struct scsi_cmnd *))
 {
        struct ata_queued_cmd *qc;
 
-       qc = ata_qc_new_init(ap, dev);
+       qc = ata_qc_new_init(dev);
        if (qc) {
                qc->scsicmd = cmd;
                qc->scsidone = done;
@@ -397,18 +394,18 @@ void ata_dump_status(unsigned id, struct ata_taskfile *tf)
 
 int ata_scsi_device_resume(struct scsi_device *sdev)
 {
-       struct ata_port *ap = (struct ata_port *) &sdev->host->hostdata[0];
+       struct ata_port *ap = ata_shost_to_port(sdev->host);
        struct ata_device *dev = &ap->device[sdev->id];
 
-       return ata_device_resume(ap, dev);
+       return ata_device_resume(dev);
 }
 
 int ata_scsi_device_suspend(struct scsi_device *sdev, pm_message_t state)
 {
-       struct ata_port *ap = (struct ata_port *) &sdev->host->hostdata[0];
+       struct ata_port *ap = ata_shost_to_port(sdev->host);
        struct ata_device *dev = &ap->device[sdev->id];
 
-       return ata_device_suspend(ap, dev, state);
+       return ata_device_suspend(dev, state);
 }
 
 /**
@@ -419,6 +416,7 @@ int ata_scsi_device_suspend(struct scsi_device *sdev, pm_message_t state)
  *     @sk: the sense key we'll fill out
  *     @asc: the additional sense code we'll fill out
  *     @ascq: the additional sense code qualifier we'll fill out
+ *     @verbose: be verbose
  *
  *     Converts an ATA error into a SCSI error.  Fill out pointers to
  *     SK, ASC, and ASCQ bytes for later use in fixed or descriptor
@@ -428,7 +426,7 @@ int ata_scsi_device_suspend(struct scsi_device *sdev, pm_message_t state)
  *     spin_lock_irqsave(host_set lock)
  */
 void ata_to_sense_error(unsigned id, u8 drv_stat, u8 drv_err, u8 *sk, u8 *asc,
-                       u8 *ascq)
+                       u8 *ascq, int verbose)
 {
        int i;
 
@@ -493,8 +491,9 @@ void ata_to_sense_error(unsigned id, u8 drv_stat, u8 drv_err, u8 *sk, u8 *asc,
                        }
                }
                /* No immediate match */
-               printk(KERN_WARNING "ata%u: no sense translation for "
-                      "error 0x%02x\n", id, drv_err);
+               if (verbose)
+                       printk(KERN_WARNING "ata%u: no sense translation for "
+                              "error 0x%02x\n", id, drv_err);
        }
 
        /* Fall back to interpreting status bits */
@@ -507,8 +506,9 @@ void ata_to_sense_error(unsigned id, u8 drv_stat, u8 drv_err, u8 *sk, u8 *asc,
                }
        }
        /* No error?  Undecoded? */
-       printk(KERN_WARNING "ata%u: no sense translation for status: 0x%02x\n",
-              id, drv_stat);
+       if (verbose)
+               printk(KERN_WARNING "ata%u: no sense translation for "
+                      "status: 0x%02x\n", id, drv_stat);
 
        /* We need a sensible error return here, which is tricky, and one
           that won't cause people to do things like return a disk wrongly */
@@ -517,9 +517,10 @@ void ata_to_sense_error(unsigned id, u8 drv_stat, u8 drv_err, u8 *sk, u8 *asc,
        *ascq = 0x00;
 
  translate_done:
-       printk(KERN_ERR "ata%u: translated ATA stat/err 0x%02x/%02x to "
-              "SCSI SK/ASC/ASCQ 0x%x/%02x/%02x\n", id, drv_stat, drv_err,
-              *sk, *asc, *ascq);
+       if (verbose)
+               printk(KERN_ERR "ata%u: translated ATA stat/err 0x%02x/%02x "
+                      "to SCSI SK/ASC/ASCQ 0x%x/%02x/%02x\n",
+                      id, drv_stat, drv_err, *sk, *asc, *ascq);
        return;
 }
 
@@ -539,27 +540,23 @@ void ata_to_sense_error(unsigned id, u8 drv_stat, u8 drv_err, u8 *sk, u8 *asc,
 void ata_gen_ata_desc_sense(struct ata_queued_cmd *qc)
 {
        struct scsi_cmnd *cmd = qc->scsicmd;
-       struct ata_taskfile *tf = &qc->tf;
+       struct ata_taskfile *tf = &qc->result_tf;
        unsigned char *sb = cmd->sense_buffer;
        unsigned char *desc = sb + 8;
+       int verbose = qc->ap->ops->error_handler == NULL;
 
        memset(sb, 0, SCSI_SENSE_BUFFERSIZE);
 
        cmd->result = (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION;
 
-       /*
-        * Read the controller registers.
-        */
-       WARN_ON(qc->ap->ops->tf_read == NULL);
-       qc->ap->ops->tf_read(qc->ap, tf);
-
        /*
         * Use ata_to_sense_error() to map status register bits
         * onto sense key, asc & ascq.
         */
-       if (tf->command & (ATA_BUSY | ATA_DF | ATA_ERR | ATA_DRQ)) {
+       if (qc->err_mask ||
+           tf->command & (ATA_BUSY | ATA_DF | ATA_ERR | ATA_DRQ)) {
                ata_to_sense_error(qc->ap->id, tf->command, tf->feature,
-                                  &sb[1], &sb[2], &sb[3]);
+                                  &sb[1], &sb[2], &sb[3], verbose);
                sb[1] &= 0x0f;
        }
 
@@ -615,26 +612,22 @@ void ata_gen_ata_desc_sense(struct ata_queued_cmd *qc)
 void ata_gen_fixed_sense(struct ata_queued_cmd *qc)
 {
        struct scsi_cmnd *cmd = qc->scsicmd;
-       struct ata_taskfile *tf = &qc->tf;
+       struct ata_taskfile *tf = &qc->result_tf;
        unsigned char *sb = cmd->sense_buffer;
+       int verbose = qc->ap->ops->error_handler == NULL;
 
        memset(sb, 0, SCSI_SENSE_BUFFERSIZE);
 
        cmd->result = (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION;
 
-       /*
-        * Read the controller registers.
-        */
-       WARN_ON(qc->ap->ops->tf_read == NULL);
-       qc->ap->ops->tf_read(qc->ap, tf);
-
        /*
         * Use ata_to_sense_error() to map status register bits
         * onto sense key, asc & ascq.
         */
-       if (tf->command & (ATA_BUSY | ATA_DF | ATA_ERR | ATA_DRQ)) {
+       if (qc->err_mask ||
+           tf->command & (ATA_BUSY | ATA_DF | ATA_ERR | ATA_DRQ)) {
                ata_to_sense_error(qc->ap->id, tf->command, tf->feature,
-                                  &sb[2], &sb[12], &sb[13]);
+                                  &sb[2], &sb[12], &sb[13], verbose);
                sb[2] &= 0x0f;
        }
 
@@ -677,7 +670,7 @@ static void ata_scsi_dev_config(struct scsi_device *sdev,
         */
        max_sectors = ATA_MAX_SECTORS;
        if (dev->flags & ATA_DFLAG_LBA48)
-               max_sectors = 2048;
+               max_sectors = ATA_MAX_SECTORS_LBA48;
        if (dev->max_sectors)
                max_sectors = dev->max_sectors;
 
@@ -692,6 +685,14 @@ static void ata_scsi_dev_config(struct scsi_device *sdev,
                request_queue_t *q = sdev->request_queue;
                blk_queue_max_hw_segments(q, q->max_hw_segments - 1);
        }
+
+       if (dev->flags & ATA_DFLAG_NCQ) {
+               int depth;
+
+               depth = min(sdev->host->can_queue, ata_id_queue_depth(dev->id));
+               depth = min(ATA_MAX_QUEUE - 1, depth);
+               scsi_adjust_queue_depth(sdev, MSG_SIMPLE_TAG, depth);
+       }
 }
 
 /**
@@ -716,7 +717,7 @@ int ata_scsi_slave_config(struct scsi_device *sdev)
                struct ata_port *ap;
                struct ata_device *dev;
 
-               ap = (struct ata_port *) &sdev->host->hostdata[0];
+               ap = ata_shost_to_port(sdev->host);
                dev = &ap->device[sdev->id];
 
                ata_scsi_dev_config(sdev, dev);
@@ -726,134 +727,40 @@ int ata_scsi_slave_config(struct scsi_device *sdev)
 }
 
 /**
- *     ata_scsi_timed_out - SCSI layer time out callback
- *     @cmd: timed out SCSI command
+ *     ata_scsi_change_queue_depth - SCSI callback for queue depth config
+ *     @sdev: SCSI device to configure queue depth for
+ *     @queue_depth: new queue depth
  *
- *     Handles SCSI layer timeout.  We race with normal completion of
- *     the qc for @cmd.  If the qc is already gone, we lose and let
- *     the scsi command finish (EH_HANDLED).  Otherwise, the qc has
- *     timed out and EH should be invoked.  Prevent ata_qc_complete()
- *     from finishing it by setting EH_SCHEDULED and return
- *     EH_NOT_HANDLED.
+ *     This is libata standard hostt->change_queue_depth callback.
+ *     SCSI will call into this callback when user tries to set queue
+ *     depth via sysfs.
  *
  *     LOCKING:
- *     Called from timer context
+ *     SCSI layer (we don't care)
  *
  *     RETURNS:
- *     EH_HANDLED or EH_NOT_HANDLED
- */
-enum scsi_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd)
-{
-       struct Scsi_Host *host = cmd->device->host;
-       struct ata_port *ap = (struct ata_port *) &host->hostdata[0];
-       unsigned long flags;
-       struct ata_queued_cmd *qc;
-       enum scsi_eh_timer_return ret = EH_HANDLED;
-
-       DPRINTK("ENTER\n");
-
-       spin_lock_irqsave(&ap->host_set->lock, flags);
-       qc = ata_qc_from_tag(ap, ap->active_tag);
-       if (qc) {
-               WARN_ON(qc->scsicmd != cmd);
-               qc->flags |= ATA_QCFLAG_EH_SCHEDULED;
-               qc->err_mask |= AC_ERR_TIMEOUT;
-               ret = EH_NOT_HANDLED;
-       }
-       spin_unlock_irqrestore(&ap->host_set->lock, flags);
-
-       DPRINTK("EXIT, ret=%d\n", ret);
-       return ret;
-}
-
-/**
- *     ata_scsi_error - SCSI layer error handler callback
- *     @host: SCSI host on which error occurred
- *
- *     Handles SCSI-layer-thrown error events.
- *
- *     LOCKING:
- *     Inherited from SCSI layer (none, can sleep)
+ *     Newly configured queue depth.
  */
-
-static void ata_scsi_error(struct Scsi_Host *host)
-{
-       struct ata_port *ap;
-       unsigned long flags;
-
-       DPRINTK("ENTER\n");
-
-       ap = (struct ata_port *) &host->hostdata[0];
-
-       spin_lock_irqsave(&ap->host_set->lock, flags);
-       WARN_ON(ap->flags & ATA_FLAG_IN_EH);
-       ap->flags |= ATA_FLAG_IN_EH;
-       WARN_ON(ata_qc_from_tag(ap, ap->active_tag) == NULL);
-       spin_unlock_irqrestore(&ap->host_set->lock, flags);
-
-       ata_port_flush_task(ap);
-
-       ap->ops->eng_timeout(ap);
-
-       WARN_ON(host->host_failed || !list_empty(&host->eh_cmd_q));
-
-       scsi_eh_flush_done_q(&ap->eh_done_q);
-
-       spin_lock_irqsave(&ap->host_set->lock, flags);
-       ap->flags &= ~ATA_FLAG_IN_EH;
-       spin_unlock_irqrestore(&ap->host_set->lock, flags);
-
-       DPRINTK("EXIT\n");
-}
-
-static void ata_eh_scsidone(struct scsi_cmnd *scmd)
+int ata_scsi_change_queue_depth(struct scsi_device *sdev, int queue_depth)
 {
-       /* nada */
-}
-
-static void __ata_eh_qc_complete(struct ata_queued_cmd *qc)
-{
-       struct ata_port *ap = qc->ap;
-       struct scsi_cmnd *scmd = qc->scsicmd;
-       unsigned long flags;
+       struct ata_port *ap = ata_shost_to_port(sdev->host);
+       struct ata_device *dev;
+       int max_depth;
 
-       spin_lock_irqsave(&ap->host_set->lock, flags);
-       qc->scsidone = ata_eh_scsidone;
-       __ata_qc_complete(qc);
-       WARN_ON(ata_tag_valid(qc->tag));
-       spin_unlock_irqrestore(&ap->host_set->lock, flags);
+       if (queue_depth < 1)
+               return sdev->queue_depth;
 
-       scsi_eh_finish_cmd(scmd, &ap->eh_done_q);
-}
+       dev = ata_scsi_find_dev(ap, sdev);
+       if (!dev || !ata_dev_enabled(dev))
+               return sdev->queue_depth;
 
-/**
- *     ata_eh_qc_complete - Complete an active ATA command from EH
- *     @qc: Command to complete
- *
- *     Indicate to the mid and upper layers that an ATA command has
- *     completed.  To be used from EH.
- */
-void ata_eh_qc_complete(struct ata_queued_cmd *qc)
-{
-       struct scsi_cmnd *scmd = qc->scsicmd;
-       scmd->retries = scmd->allowed;
-       __ata_eh_qc_complete(qc);
-}
+       max_depth = min(sdev->host->can_queue, ata_id_queue_depth(dev->id));
+       max_depth = min(ATA_MAX_QUEUE - 1, max_depth);
+       if (queue_depth > max_depth)
+               queue_depth = max_depth;
 
-/**
- *     ata_eh_qc_retry - Tell midlayer to retry an ATA command after EH
- *     @qc: Command to retry
- *
- *     Indicate to the mid and upper layers that an ATA command
- *     should be retried.  To be used from EH.
- *
- *     SCSI midlayer limits the number of retries to scmd->allowed.
- *     This function might need to adjust scmd->retries for commands
- *     which get retried due to unrelated NCQ failures.
- */
-void ata_eh_qc_retry(struct ata_queued_cmd *qc)
-{
-       __ata_eh_qc_complete(qc);
+       scsi_adjust_queue_depth(sdev, MSG_SIMPLE_TAG, queue_depth);
+       return queue_depth;
 }
 
 /**
@@ -891,7 +798,7 @@ static unsigned int ata_scsi_start_stop_xlat(struct ata_queued_cmd *qc,
                tf->nsect = 1;  /* 1 sector, lba=0 */
 
                if (qc->dev->flags & ATA_DFLAG_LBA) {
-                       qc->tf.flags |= ATA_TFLAG_LBA;
+                       tf->flags |= ATA_TFLAG_LBA;
 
                        tf->lbah = 0x0;
                        tf->lbam = 0x0;
@@ -1195,6 +1102,7 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, const u8 *scsicm
        u64 block;
        u32 n_block;
 
+       qc->flags |= ATA_QCFLAG_IO;
        tf->flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
 
        if (scsicmd[0] == WRITE_10 || scsicmd[0] == WRITE_6 ||
@@ -1241,7 +1149,36 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, const u8 *scsicm
                 */
                goto nothing_to_do;
 
-       if (dev->flags & ATA_DFLAG_LBA) {
+       if ((dev->flags & (ATA_DFLAG_PIO | ATA_DFLAG_NCQ)) == ATA_DFLAG_NCQ) {
+               /* yay, NCQ */
+               if (!lba_48_ok(block, n_block))
+                       goto out_of_range;
+
+               tf->protocol = ATA_PROT_NCQ;
+               tf->flags |= ATA_TFLAG_LBA | ATA_TFLAG_LBA48;
+
+               if (tf->flags & ATA_TFLAG_WRITE)
+                       tf->command = ATA_CMD_FPDMA_WRITE;
+               else
+                       tf->command = ATA_CMD_FPDMA_READ;
+
+               qc->nsect = n_block;
+
+               tf->nsect = qc->tag << 3;
+               tf->hob_feature = (n_block >> 8) & 0xff;
+               tf->feature = n_block & 0xff;
+
+               tf->hob_lbah = (block >> 40) & 0xff;
+               tf->hob_lbam = (block >> 32) & 0xff;
+               tf->hob_lbal = (block >> 24) & 0xff;
+               tf->lbah = (block >> 16) & 0xff;
+               tf->lbam = (block >> 8) & 0xff;
+               tf->lbal = block & 0xff;
+
+               tf->device = 1 << 6;
+               if (tf->flags & ATA_TFLAG_FUA)
+                       tf->device |= 1 << 7;
+       } else if (dev->flags & ATA_DFLAG_LBA) {
                tf->flags |= ATA_TFLAG_LBA;
 
                if (lba_28_ok(block, n_block)) {
@@ -1356,19 +1293,49 @@ static void ata_scsi_qc_complete(struct ata_queued_cmd *qc)
                }
        }
 
-       if (need_sense) {
-               /* The ata_gen_..._sense routines fill in tf */
-               ata_dump_status(qc->ap->id, &qc->tf);
-       }
+       if (need_sense && !qc->ap->ops->error_handler)
+               ata_dump_status(qc->ap->id, &qc->result_tf);
 
        qc->scsidone(cmd);
 
        ata_qc_free(qc);
 }
 
+/**
+ *     ata_scmd_need_defer - Check whether we need to defer scmd
+ *     @dev: ATA device to which the command is addressed
+ *     @is_io: Is the command IO (and thus possibly NCQ)?
+ *
+ *     NCQ and non-NCQ commands cannot run together.  As upper layer
+ *     only knows the queue depth, we are responsible for maintaining
+ *     exclusion.  This function checks whether a new command can be
+ *     issued to @dev.
+ *
+ *     LOCKING:
+ *     spin_lock_irqsave(host_set lock)
+ *
+ *     RETURNS:
+ *     1 if deferring is needed, 0 otherwise.
+ */
+static int ata_scmd_need_defer(struct ata_device *dev, int is_io)
+{
+       struct ata_port *ap = dev->ap;
+
+       if (!(dev->flags & ATA_DFLAG_NCQ))
+               return 0;
+
+       if (is_io) {
+               if (!ata_tag_valid(ap->active_tag))
+                       return 0;
+       } else {
+               if (!ata_tag_valid(ap->active_tag) && !ap->sactive)
+                       return 0;
+       }
+       return 1;
+}
+
 /**
  *     ata_scsi_translate - Translate then issue SCSI command to ATA device
- *     @ap: ATA port to which the command is addressed
  *     @dev: ATA device to which the command is addressed
  *     @cmd: SCSI command to execute
  *     @done: SCSI command completion function
@@ -1389,19 +1356,25 @@ static void ata_scsi_qc_complete(struct ata_queued_cmd *qc)
  *
  *     LOCKING:
  *     spin_lock_irqsave(host_set lock)
+ *
+ *     RETURNS:
+ *     0 on success, SCSI_ML_QUEUE_DEVICE_BUSY if the command
+ *     needs to be deferred.
  */
-
-static void ata_scsi_translate(struct ata_port *ap, struct ata_device *dev,
-                             struct scsi_cmnd *cmd,
+static int ata_scsi_translate(struct ata_device *dev, struct scsi_cmnd *cmd,
                              void (*done)(struct scsi_cmnd *),
                              ata_xlat_func_t xlat_func)
 {
        struct ata_queued_cmd *qc;
        u8 *scsicmd = cmd->cmnd;
+       int is_io = xlat_func == ata_scsi_rw_xlat;
 
        VPRINTK("ENTER\n");
 
-       qc = ata_scsi_qc_new(ap, dev, cmd, done);
+       if (unlikely(ata_scmd_need_defer(dev, is_io)))
+               goto defer;
+
+       qc = ata_scsi_qc_new(dev, cmd, done);
        if (!qc)
                goto err_mem;
 
@@ -1409,8 +1382,8 @@ static void ata_scsi_translate(struct ata_port *ap, struct ata_device *dev,
        if (cmd->sc_data_direction == DMA_FROM_DEVICE ||
            cmd->sc_data_direction == DMA_TO_DEVICE) {
                if (unlikely(cmd->request_bufflen < 1)) {
-                       printk(KERN_WARNING "ata%u(%u): WARNING: zero len r/w req\n",
-                              ap->id, dev->devno);
+                       ata_dev_printk(dev, KERN_WARNING,
+                                      "WARNING: zero len r/w req\n");
                        goto err_did;
                }
 
@@ -1432,13 +1405,13 @@ static void ata_scsi_translate(struct ata_port *ap, struct ata_device *dev,
        ata_qc_issue(qc);
 
        VPRINTK("EXIT\n");
-       return;
+       return 0;
 
 early_finish:
         ata_qc_free(qc);
        done(cmd);
        DPRINTK("EXIT - early finish (good or error)\n");
-       return;
+       return 0;
 
 err_did:
        ata_qc_free(qc);
@@ -1446,7 +1419,11 @@ err_mem:
        cmd->result = (DID_ERROR << 16);
        done(cmd);
        DPRINTK("EXIT - internal\n");
-       return;
+       return 0;
+
+defer:
+       DPRINTK("EXIT - defer\n");
+       return SCSI_MLQUEUE_DEVICE_BUSY;
 }
 
 /**
@@ -2137,13 +2114,14 @@ void ata_scsi_badcmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *), u8
 
 static void atapi_sense_complete(struct ata_queued_cmd *qc)
 {
-       if (qc->err_mask && ((qc->err_mask & AC_ERR_DEV) == 0))
+       if (qc->err_mask && ((qc->err_mask & AC_ERR_DEV) == 0)) {
                /* FIXME: not quite right; we don't want the
                 * translation of taskfile registers into
                 * a sense descriptors, since that's only
                 * correct for ATA, not ATAPI
                 */
                ata_gen_ata_desc_sense(qc);
+       }
 
        qc->scsidone(qc->scsicmd);
        ata_qc_free(qc);
@@ -2207,21 +2185,38 @@ static void atapi_qc_complete(struct ata_queued_cmd *qc)
 
        VPRINTK("ENTER, err_mask 0x%X\n", err_mask);
 
+       /* handle completion from new EH */
+       if (unlikely(qc->ap->ops->error_handler &&
+                    (err_mask || qc->flags & ATA_QCFLAG_SENSE_VALID))) {
+
+               if (!(qc->flags & ATA_QCFLAG_SENSE_VALID)) {
+                       /* FIXME: not quite right; we don't want the
+                        * translation of taskfile registers into a
+                        * sense descriptors, since that's only
+                        * correct for ATA, not ATAPI
+                        */
+                       ata_gen_ata_desc_sense(qc);
+               }
+
+               qc->scsicmd->result = SAM_STAT_CHECK_CONDITION;
+               qc->scsidone(cmd);
+               ata_qc_free(qc);
+               return;
+       }
+
+       /* successful completion or old EH failure path */
        if (unlikely(err_mask & AC_ERR_DEV)) {
                cmd->result = SAM_STAT_CHECK_CONDITION;
                atapi_request_sense(qc);
                return;
-       }
-
-       else if (unlikely(err_mask))
+       } else if (unlikely(err_mask)) {
                /* FIXME: not quite right; we don't want the
                 * translation of taskfile registers into
                 * a sense descriptors, since that's only
                 * correct for ATA, not ATAPI
                 */
                ata_gen_ata_desc_sense(qc);
-
-       else {
+       } else {
                u8 *scsicmd = cmd->cmnd;
 
                if ((scsicmd[0] == INQUIRY) && ((scsicmd[1] & 0x03) == 0)) {
@@ -2303,11 +2298,9 @@ static unsigned int atapi_xlat(struct ata_queued_cmd *qc, const u8 *scsicmd)
                qc->tf.protocol = ATA_PROT_ATAPI_DMA;
                qc->tf.feature |= ATAPI_PKT_DMA;
 
-#ifdef ATAPI_ENABLE_DMADIR
-               /* some SATA bridges need us to indicate data xfer direction */
-               if (cmd->sc_data_direction != DMA_TO_DEVICE)
+               if (atapi_dmadir && (cmd->sc_data_direction != DMA_TO_DEVICE))
+                       /* some SATA bridges need us to indicate data xfer direction */
                        qc->tf.feature |= ATAPI_DMADIR;
-#endif
        }
 
        qc->nbytes = cmd->bufflen;
@@ -2347,13 +2340,14 @@ ata_scsi_find_dev(struct ata_port *ap, const struct scsi_device *scsidev)
                     (scsidev->lun != 0)))
                return NULL;
 
-       if (unlikely(!ata_dev_present(dev)))
+       if (unlikely(!ata_dev_enabled(dev)))
                return NULL;
 
        if (!atapi_enabled || (ap->flags & ATA_FLAG_NO_ATAPI)) {
                if (unlikely(dev->class == ATA_DEV_ATAPI)) {
-                       printk(KERN_WARNING "ata%u(%u): WARNING: ATAPI is %s, device ignored.\n",
-                              ap->id, dev->devno, atapi_enabled ? "not supported with this driver" : "disabled");
+                       ata_dev_printk(dev, KERN_WARNING,
+                               "WARNING: ATAPI is %s, device ignored.\n",
+                               atapi_enabled ? "not supported with this driver" : "disabled");
                        return NULL;
                }
        }
@@ -2502,6 +2496,9 @@ ata_scsi_pass_thru(struct ata_queued_cmd *qc, const u8 *scsicmd)
         */
        qc->nsect = cmd->bufflen / ATA_SECT_SIZE;
 
+       /* request result TF */
+       qc->flags |= ATA_QCFLAG_RESULT_TF;
+
        return 0;
 
  invalid_fld:
@@ -2578,19 +2575,24 @@ static inline void ata_scsi_dump_cdb(struct ata_port *ap,
 #endif
 }
 
-static inline void __ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *),
-                                      struct ata_port *ap, struct ata_device *dev)
+static inline int __ata_scsi_queuecmd(struct scsi_cmnd *cmd,
+                                     void (*done)(struct scsi_cmnd *),
+                                     struct ata_device *dev)
 {
+       int rc = 0;
+
        if (dev->class == ATA_DEV_ATA) {
                ata_xlat_func_t xlat_func = ata_get_xlat_func(dev,
                                                              cmd->cmnd[0]);
 
                if (xlat_func)
-                       ata_scsi_translate(ap, dev, cmd, done, xlat_func);
+                       rc = ata_scsi_translate(dev, cmd, done, xlat_func);
                else
-                       ata_scsi_simulate(ap, dev, cmd, done);
+                       ata_scsi_simulate(dev, cmd, done);
        } else
-               ata_scsi_translate(ap, dev, cmd, done, atapi_xlat);
+               rc = ata_scsi_translate(dev, cmd, done, atapi_xlat);
+
+       return rc;
 }
 
 /**
@@ -2609,17 +2611,18 @@ static inline void __ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struc
  *     Releases scsi-layer-held lock, and obtains host_set lock.
  *
  *     RETURNS:
- *     Zero.
+ *     Return value from __ata_scsi_queuecmd() if @cmd can be queued,
+ *     0 otherwise.
  */
-
 int ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
 {
        struct ata_port *ap;
        struct ata_device *dev;
        struct scsi_device *scsidev = cmd->device;
        struct Scsi_Host *shost = scsidev->host;
+       int rc = 0;
 
-       ap = (struct ata_port *) &shost->hostdata[0];
+       ap = ata_shost_to_port(shost);
 
        spin_unlock(shost->host_lock);
        spin_lock(&ap->host_set->lock);
@@ -2628,7 +2631,7 @@ int ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
 
        dev = ata_scsi_find_dev(ap, scsidev);
        if (likely(dev))
-               __ata_scsi_queuecmd(cmd, done, ap, dev);
+               rc = __ata_scsi_queuecmd(cmd, done, dev);
        else {
                cmd->result = (DID_BAD_TARGET << 16);
                done(cmd);
@@ -2636,12 +2639,11 @@ int ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
 
        spin_unlock(&ap->host_set->lock);
        spin_lock(shost->host_lock);
-       return 0;
+       return rc;
 }
 
 /**
  *     ata_scsi_simulate - simulate SCSI command on ATA device
- *     @ap: port the device is connected to
  *     @dev: the target device
  *     @cmd: SCSI command being sent to device.
  *     @done: SCSI command completion function.
@@ -2653,14 +2655,12 @@ int ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
  *     spin_lock_irqsave(host_set lock)
  */
 
-void ata_scsi_simulate(struct ata_port *ap, struct ata_device *dev,
-                     struct scsi_cmnd *cmd,
+void ata_scsi_simulate(struct ata_device *dev, struct scsi_cmnd *cmd,
                      void (*done)(struct scsi_cmnd *))
 {
        struct ata_scsi_args args;
        const u8 *scsicmd = cmd->cmnd;
 
-       args.ap = ap;
        args.dev = dev;
        args.id = dev->id;
        args.cmd = cmd;
@@ -2735,14 +2735,13 @@ void ata_scsi_scan_host(struct ata_port *ap)
        struct ata_device *dev;
        unsigned int i;
 
-       if (ap->flags & ATA_FLAG_PORT_DISABLED)
+       if (ap->flags & ATA_FLAG_DISABLED)
                return;
 
        for (i = 0; i < ATA_MAX_DEVICES; i++) {
                dev = &ap->device[i];
 
-               if (ata_dev_present(dev))
+               if (ata_dev_enabled(dev))
                        scsi_scan_target(&ap->host->shost_gendev, 0, i, 0, 0);
        }
 }
-
index bac8cba..b76ad7d 100644 (file)
 #define __LIBATA_H__
 
 #define DRV_NAME       "libata"
-#define DRV_VERSION    "1.20"  /* must be exactly four chars */
+#define DRV_VERSION    "1.30"  /* must be exactly four chars */
 
 struct ata_scsi_args {
-       struct ata_port         *ap;
        struct ata_device       *dev;
        u16                     *id;
        struct scsi_cmnd        *cmd;
@@ -41,13 +40,24 @@ struct ata_scsi_args {
 
 /* libata-core.c */
 extern int atapi_enabled;
+extern int atapi_dmadir;
 extern int libata_fua;
-extern struct ata_queued_cmd *ata_qc_new_init(struct ata_port *ap,
-                                     struct ata_device *dev);
+extern struct ata_queued_cmd *ata_qc_new_init(struct ata_device *dev);
 extern int ata_rwcmd_protocol(struct ata_queued_cmd *qc);
+extern void ata_dev_disable(struct ata_device *dev);
 extern void ata_port_flush_task(struct ata_port *ap);
+extern unsigned ata_exec_internal(struct ata_device *dev,
+                                 struct ata_taskfile *tf, const u8 *cdb,
+                                 int dma_dir, void *buf, unsigned int buflen);
+extern int sata_down_spd_limit(struct ata_port *ap);
+extern int sata_set_spd_needed(struct ata_port *ap);
+extern int ata_down_xfermask_limit(struct ata_device *dev, int force_pio0);
+extern int ata_set_mode(struct ata_port *ap, struct ata_device **r_failed_dev);
+extern int ata_do_reset(struct ata_port *ap, ata_reset_fn_t reset,
+                       unsigned int *classes);
 extern void ata_qc_free(struct ata_queued_cmd *qc);
 extern void ata_qc_issue(struct ata_queued_cmd *qc);
+extern void __ata_qc_complete(struct ata_queued_cmd *qc);
 extern int ata_check_atapi_dma(struct ata_queued_cmd *qc);
 extern void ata_dev_select(struct ata_port *ap, unsigned int device,
                            unsigned int wait, unsigned int can_sleep);
@@ -88,5 +98,11 @@ extern void ata_scsi_set_sense(struct scsi_cmnd *cmd,
 extern void ata_scsi_rbuf_fill(struct ata_scsi_args *args,
                         unsigned int (*actor) (struct ata_scsi_args *args,
                                            u8 *rbuf, unsigned int buflen));
+extern void ata_schedule_scsi_eh(struct Scsi_Host *shost);
+
+/* libata-eh.c */
+extern enum scsi_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd);
+extern void ata_scsi_error(struct Scsi_Host *host);
+extern void ata_qc_schedule_eh(struct ata_queued_cmd *qc);
 
 #endif /* __LIBATA_H__ */
index 5cda16c..a341fa8 100644 (file)
@@ -46,7 +46,7 @@
 #include <linux/libata.h>
 
 #define DRV_NAME       "pdc_adma"
-#define DRV_VERSION    "0.03"
+#define DRV_VERSION    "0.04"
 
 /* macro to calculate base address for ATA regs */
 #define ADMA_ATA_REGS(base,port_no)    ((base) + ((port_no) * 0x40))
@@ -455,13 +455,13 @@ static inline unsigned int adma_intr_pkt(struct ata_host_set *host_set)
                        continue;
                handled = 1;
                adma_enter_reg_mode(ap);
-               if (ap->flags & (ATA_FLAG_PORT_DISABLED | ATA_FLAG_NOINTR))
+               if (ap->flags & ATA_FLAG_DISABLED)
                        continue;
                pp = ap->private_data;
                if (!pp || pp->state != adma_state_pkt)
                        continue;
                qc = ata_qc_from_tag(ap, ap->active_tag);
-               if (qc && (!(qc->tf.ctl & ATA_NIEN))) {
+               if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING))) {
                        if ((status & (aPERR | aPSD | aUIRQ)))
                                qc->err_mask |= AC_ERR_OTHER;
                        else if (pp->pkt[0] != cDONE)
@@ -480,13 +480,13 @@ static inline unsigned int adma_intr_mmio(struct ata_host_set *host_set)
        for (port_no = 0; port_no < host_set->n_ports; ++port_no) {
                struct ata_port *ap;
                ap = host_set->ports[port_no];
-               if (ap && (!(ap->flags & (ATA_FLAG_PORT_DISABLED | ATA_FLAG_NOINTR)))) {
+               if (ap && (!(ap->flags & ATA_FLAG_DISABLED))) {
                        struct ata_queued_cmd *qc;
                        struct adma_port_priv *pp = ap->private_data;
                        if (!pp || pp->state != adma_state_mmio)
                                continue;
                        qc = ata_qc_from_tag(ap, ap->active_tag);
-                       if (qc && (!(qc->tf.ctl & ATA_NIEN))) {
+                       if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING))) {
 
                                /* check main status, clearing INTRQ */
                                u8 status = ata_check_status(ap);
index 9b8bca1..bfe817f 100644 (file)
@@ -93,7 +93,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),
@@ -683,7 +683,7 @@ static void mv_stop_dma(struct ata_port *ap)
        }
 
        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 */
        }
 }
@@ -1307,8 +1307,8 @@ static void mv_err_intr(struct ata_port *ap, int reset_allowed)
        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;
@@ -1398,7 +1398,7 @@ static void mv_host_intr(struct ata_host_set *host_set, u32 relevant,
                        }
                }
 
-               if (ap->flags & (ATA_FLAG_PORT_DISABLED | ATA_FLAG_NOINTR))
+               if (ap && (ap->flags & ATA_FLAG_DISABLED))
                        continue;
 
                err_mask = ac_err_mask(ata_status);
@@ -1419,7 +1419,7 @@ static void mv_host_intr(struct ata_host_set *host_set, u32 relevant,
                                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);
                                }
@@ -1949,15 +1949,16 @@ static void __mv_phy_reset(struct ata_port *ap, int can_sleep)
 
        /* 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;
 
@@ -1974,11 +1975,12 @@ comreset_retry:
                "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;
        }
@@ -2005,7 +2007,7 @@ comreset_retry:
        tf.nsect = readb((void __iomem *) ap->ioaddr.nsect_addr);
 
        dev->class = ata_dev_classify(&tf);
-       if (!ata_dev_present(dev)) {
+       if (!ata_dev_enabled(dev)) {
                VPRINTK("Port disabled post-sig: No device present.\n");
                ata_port_disable(ap);
        }
@@ -2036,7 +2038,7 @@ static void mv_eng_timeout(struct ata_port *ap)
 {
        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 9f55308..043ff4f 100644 (file)
@@ -44,7 +44,7 @@
 #include <linux/libata.h>
 
 #define DRV_NAME                       "sata_nv"
-#define DRV_VERSION                    "0.8"
+#define DRV_VERSION                    "0.9"
 
 enum {
        NV_PORTS                        = 2,
@@ -140,6 +140,12 @@ static const struct pci_device_id nv_pci_tbl[] = {
                PCI_ANY_ID, PCI_ANY_ID, 0, 0, GENERIC },
        { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SATA2,
                PCI_ANY_ID, PCI_ANY_ID, 0, 0, GENERIC },
+       { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0, GENERIC },
+       { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA2,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0, GENERIC },
+       { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA3,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0, GENERIC },
        { PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID,
                PCI_ANY_ID, PCI_ANY_ID,
                PCI_CLASS_STORAGE_IDE<<8, 0xffff00, GENERIC },
@@ -279,11 +285,11 @@ static irqreturn_t nv_interrupt (int irq, void *dev_instance,
 
                ap = host_set->ports[i];
                if (ap &&
-                   !(ap->flags & (ATA_FLAG_PORT_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 += ata_host_intr(ap, qc);
                        else
                                // No request pending?  Clear interrupt status
index 7eb67a6..285ab02 100644 (file)
@@ -76,7 +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,
 };
 
 
@@ -363,12 +364,23 @@ static void pdc_sata_phy_reset(struct ata_port *ap)
        sata_phy_reset(ap);
 }
 
-static void pdc_pata_phy_reset(struct ata_port *ap)
+static void pdc_pata_cbl_detect(struct ata_port *ap)
 {
-       /* FIXME: add cable detect.  Don't assume 40-pin cable */
-       ap->cbl = ATA_CBL_PATA40;
-       ap->udma_mask &= ATA_UDMA_MASK_40C;
+       u8 tmp;
+       void __iomem *mmio = (void *) ap->ioaddr.cmd_addr + PDC_CTLSTAT + 0x03;
+
+       tmp = readb(mmio);
+
+       if (tmp & 0x01) {
+               ap->cbl = ATA_CBL_PATA40;
+               ap->udma_mask &= ATA_UDMA_MASK_40C;
+       } else
+               ap->cbl = ATA_CBL_PATA80;
+}
 
+static void pdc_pata_phy_reset(struct ata_port *ap)
+{
+       pdc_pata_cbl_detect(ap);
        pdc_reset_port(ap);
        ata_port_probe(ap);
        ata_bus_reset(ap);
@@ -435,7 +447,7 @@ static void pdc_eng_timeout(struct ata_port *ap)
        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;
@@ -443,8 +455,9 @@ static void pdc_eng_timeout(struct ata_port *ap)
        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;
@@ -533,11 +546,11 @@ static irqreturn_t pdc_interrupt (int irq, void *dev_instance, struct pt_regs *r
                ap = host_set->ports[i];
                tmp = mask & (1 << (i + 1));
                if (tmp && ap &&
-                   !(ap->flags & (ATA_FLAG_PORT_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);
                }
        }
@@ -676,10 +689,6 @@ static int pdc_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *e
        if (!printed_version++)
                dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
 
-       /*
-        * If this driver happens to only be useful on Apple's K2, then
-        * we should check that here as it has a normal Serverworks ID
-        */
        rc = pci_enable_device(pdev);
        if (rc)
                return rc;
index 886f344..54283e0 100644 (file)
@@ -41,7 +41,7 @@
 #include <linux/libata.h>
 
 #define DRV_NAME       "sata_qstor"
-#define DRV_VERSION    "0.05"
+#define DRV_VERSION    "0.06"
 
 enum {
        QS_PORTS                = 4,
@@ -175,7 +175,7 @@ static const struct ata_port_info qs_port_info[] = {
                .host_flags     = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
                                  ATA_FLAG_SATA_RESET |
                                  //FIXME ATA_FLAG_SRST |
-                                 ATA_FLAG_MMIO,
+                                 ATA_FLAG_MMIO | ATA_FLAG_PIO_POLLING,
                .pio_mask       = 0x10, /* pio4 */
                .udma_mask      = 0x7f, /* udma0-6 */
                .port_ops       = &qs_ata_ops,
@@ -394,14 +394,13 @@ static inline unsigned int qs_intr_pkt(struct ata_host_set *host_set)
                        DPRINTK("SFF=%08x%08x: sCHAN=%u sHST=%d sDST=%02x\n",
                                        sff1, sff0, port_no, sHST, sDST);
                        handled = 1;
-                       if (ap && !(ap->flags &
-                                   (ATA_FLAG_PORT_DISABLED|ATA_FLAG_NOINTR))) {
+                       if (ap && !(ap->flags & ATA_FLAG_DISABLED)) {
                                struct ata_queued_cmd *qc;
                                struct qs_port_priv *pp = ap->private_data;
                                if (!pp || pp->state != qs_state_pkt)
                                        continue;
                                qc = ata_qc_from_tag(ap, ap->active_tag);
-                               if (qc && (!(qc->tf.ctl & ATA_NIEN))) {
+                               if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING))) {
                                        switch (sHST) {
                                        case 0: /* successful CPB */
                                        case 3: /* device error */
@@ -428,13 +427,13 @@ static inline unsigned int qs_intr_mmio(struct ata_host_set *host_set)
                struct ata_port *ap;
                ap = host_set->ports[port_no];
                if (ap &&
-                   !(ap->flags & (ATA_FLAG_PORT_DISABLED | ATA_FLAG_NOINTR))) {
+                   !(ap->flags & ATA_FLAG_DISABLED)) {
                        struct ata_queued_cmd *qc;
                        struct qs_port_priv *pp = ap->private_data;
                        if (!pp || pp->state != qs_state_mmio)
                                continue;
                        qc = ata_qc_from_tag(ap, ap->active_tag);
-                       if (qc && (!(qc->tf.ctl & ATA_NIEN))) {
+                       if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING))) {
 
                                /* check main status, clearing INTRQ */
                                u8 status = ata_check_status(ap);
index 1066272..aa63044 100644 (file)
@@ -46,7 +46,7 @@
 #include <linux/libata.h>
 
 #define DRV_NAME       "sata_sil"
-#define DRV_VERSION    "0.9"
+#define DRV_VERSION    "1.0"
 
 enum {
        /*
@@ -96,6 +96,8 @@ static void sil_dev_config(struct ata_port *ap, struct ata_device *dev);
 static u32 sil_scr_read (struct ata_port *ap, unsigned int sc_reg);
 static void sil_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val);
 static void sil_post_set_mode (struct ata_port *ap);
+static void sil_freeze(struct ata_port *ap);
+static void sil_thaw(struct ata_port *ap);
 
 
 static const struct pci_device_id sil_pci_tbl[] = {
@@ -174,7 +176,10 @@ static const struct ata_port_operations sil_ops = {
        .bmdma_status           = ata_bmdma_status,
        .qc_prep                = ata_qc_prep,
        .qc_issue               = ata_qc_issue_prot,
-       .eng_timeout            = ata_eng_timeout,
+       .freeze                 = sil_freeze,
+       .thaw                   = sil_thaw,
+       .error_handler          = ata_bmdma_error_handler,
+       .post_internal_cmd      = ata_bmdma_post_internal_cmd,
        .irq_handler            = ata_interrupt,
        .irq_clear              = ata_bmdma_irq_clear,
        .scr_read               = sil_scr_read,
@@ -263,7 +268,7 @@ static void sil_post_set_mode (struct ata_port *ap)
 
        for (i = 0; i < 2; i++) {
                dev = &ap->device[i];
-               if (!ata_dev_present(dev))
+               if (!ata_dev_enabled(dev))
                        dev_mode[i] = 0;        /* PIO0/1/2 */
                else if (dev->flags & ATA_DFLAG_PIO)
                        dev_mode[i] = 1;        /* PIO3/4 */
@@ -314,6 +319,33 @@ static void sil_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val)
                writel(val, mmio);
 }
 
+static void sil_freeze(struct ata_port *ap)
+{
+       void __iomem *mmio_base = ap->host_set->mmio_base;
+       u32 tmp;
+
+       /* plug IRQ */
+       tmp = readl(mmio_base + SIL_SYSCFG);
+       tmp |= SIL_MASK_IDE0_INT << ap->port_no;
+       writel(tmp, mmio_base + SIL_SYSCFG);
+       readl(mmio_base + SIL_SYSCFG);  /* flush */
+}
+
+static void sil_thaw(struct ata_port *ap)
+{
+       void __iomem *mmio_base = ap->host_set->mmio_base;
+       u32 tmp;
+
+       /* clear IRQ */
+       ata_chk_status(ap);
+       ata_bmdma_irq_clear(ap);
+
+       /* turn on IRQ */
+       tmp = readl(mmio_base + SIL_SYSCFG);
+       tmp &= ~(SIL_MASK_IDE0_INT << ap->port_no);
+       writel(tmp, mmio_base + SIL_SYSCFG);
+}
+
 /**
  *     sil_dev_config - Apply device/host-specific errata fixups
  *     @ap: Port containing device to be examined
@@ -360,16 +392,16 @@ static void sil_dev_config(struct ata_port *ap, struct ata_device *dev)
        if (slow_down ||
            ((ap->flags & SIL_FLAG_MOD15WRITE) &&
             (quirks & SIL_QUIRK_MOD15WRITE))) {
-               printk(KERN_INFO "ata%u(%u): applying Seagate errata fix (mod15write workaround)\n",
-                      ap->id, dev->devno);
+               ata_dev_printk(dev, KERN_INFO, "applying Seagate errata fix "
+                              "(mod15write workaround)\n");
                dev->max_sectors = 15;
                return;
        }
 
        /* limit to udma5 */
        if (quirks & SIL_QUIRK_UDMA5MAX) {
-               printk(KERN_INFO "ata%u(%u): applying Maxtor errata fix %s\n",
-                      ap->id, dev->devno, model_num);
+               ata_dev_printk(dev, KERN_INFO,
+                              "applying Maxtor errata fix %s\n", model_num);
                dev->udma_mask &= ATA_UDMA5;
                return;
        }
@@ -384,16 +416,12 @@ static int sil_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
        int rc;
        unsigned int i;
        int pci_dev_busy = 0;
-       u32 tmp, irq_mask;
+       u32 tmp;
        u8 cls;
 
        if (!printed_version++)
                dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
 
-       /*
-        * If this driver happens to only be useful on Apple's K2, then
-        * we should check that here as it has a normal Serverworks ID
-        */
        rc = pci_enable_device(pdev);
        if (rc)
                return rc;
@@ -478,24 +506,11 @@ static int sil_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
        }
 
        if (ent->driver_data == sil_3114) {
-               irq_mask = SIL_MASK_4PORT;
-
                /* flip the magic "make 4 ports work" bit */
                tmp = readl(mmio_base + sil_port[2].bmdma);
                if ((tmp & SIL_INTR_STEERING) == 0)
                        writel(tmp | SIL_INTR_STEERING,
                               mmio_base + sil_port[2].bmdma);
-
-       } else {
-               irq_mask = SIL_MASK_2PORT;
-       }
-
-       /* make sure IDE0/1/2/3 interrupts are not masked */
-       tmp = readl(mmio_base + SIL_SYSCFG);
-       if (tmp & irq_mask) {
-               tmp &= ~irq_mask;
-               writel(tmp, mmio_base + SIL_SYSCFG);
-               readl(mmio_base + SIL_SYSCFG);  /* flush */
        }
 
        /* mask all SATA phy-related interrupts */
index f7264fd..4c76f05 100644 (file)
@@ -31,7 +31,7 @@
 #include <asm/io.h>
 
 #define DRV_NAME       "sata_sil24"
-#define DRV_VERSION    "0.23"
+#define DRV_VERSION    "0.24"
 
 /*
  * Port request block (PRB) 32 bytes
@@ -86,6 +86,13 @@ enum {
        /* HOST_SLOT_STAT bits */
        HOST_SSTAT_ATTN         = (1 << 31),
 
+       /* HOST_CTRL bits */
+       HOST_CTRL_M66EN         = (1 << 16), /* M66EN PCI bus signal */
+       HOST_CTRL_TRDY          = (1 << 17), /* latched PCI TRDY */
+       HOST_CTRL_STOP          = (1 << 18), /* latched PCI STOP */
+       HOST_CTRL_DEVSEL        = (1 << 19), /* latched PCI DEVSEL */
+       HOST_CTRL_REQ64         = (1 << 20), /* latched PCI REQ64 */
+
        /*
         * Port registers
         * (8192 bytes @ +0x0000, +0x2000, +0x4000 and +0x6000 @ BAR2)
@@ -142,8 +149,15 @@ enum {
        PORT_IRQ_PWR_CHG        = (1 << 3), /* power management change */
        PORT_IRQ_PHYRDY_CHG     = (1 << 4), /* PHY ready change */
        PORT_IRQ_COMWAKE        = (1 << 5), /* COMWAKE received */
-       PORT_IRQ_UNK_FIS        = (1 << 6), /* Unknown FIS received */
-       PORT_IRQ_SDB_FIS        = (1 << 11), /* SDB FIS received */
+       PORT_IRQ_UNK_FIS        = (1 << 6), /* unknown FIS received */
+       PORT_IRQ_DEV_XCHG       = (1 << 7), /* device exchanged */
+       PORT_IRQ_8B10B          = (1 << 8), /* 8b/10b decode error threshold */
+       PORT_IRQ_CRC            = (1 << 9), /* CRC error threshold */
+       PORT_IRQ_HANDSHAKE      = (1 << 10), /* handshake error threshold */
+       PORT_IRQ_SDB_NOTIFY     = (1 << 11), /* SDB notify received */
+
+       DEF_PORT_IRQ            = PORT_IRQ_COMPLETE | PORT_IRQ_ERROR |
+                                 PORT_IRQ_DEV_XCHG | PORT_IRQ_UNK_FIS,
 
        /* bits[27:16] are unmasked (raw) */
        PORT_IRQ_RAW_SHIFT      = 16,
@@ -174,7 +188,7 @@ enum {
        PORT_CERR_CMD_PCIPERR   = 27, /* ctrl[15:13] 110 - PCI parity err while fetching PRB */
        PORT_CERR_XFR_UNDEF     = 32, /* PSD ecode 00 - undefined */
        PORT_CERR_XFR_TGTABRT   = 33, /* PSD ecode 01 - target abort */
-       PORT_CERR_XFR_MSGABRT   = 34, /* PSD ecode 10 - master abort */
+       PORT_CERR_XFR_MSTABRT   = 34, /* PSD ecode 10 - master abort */
        PORT_CERR_XFR_PCIPERR   = 35, /* PSD ecode 11 - PCI prity err during transfer */
        PORT_CERR_SENDSERVICE   = 36, /* FIS received while sending service */
 
@@ -202,11 +216,19 @@ enum {
        SGE_DRD                 = (1 << 29), /* discard data read (/dev/null)
                                                data address ignored */
 
+       SIL24_MAX_CMDS          = 31,
+
        /* board id */
        BID_SIL3124             = 0,
        BID_SIL3132             = 1,
        BID_SIL3131             = 2,
 
+       /* host flags */
+       SIL24_COMMON_FLAGS      = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
+                                 ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA |
+                                 ATA_FLAG_NCQ,
+       SIL24_FLAG_PCIX_IRQ_WOC = (1 << 24), /* IRQ loss errata on PCI-X */
+
        IRQ_STAT_4PORTS         = 0xf,
 };
 
@@ -226,6 +248,58 @@ union sil24_cmd_block {
        struct sil24_atapi_block atapi;
 };
 
+static struct sil24_cerr_info {
+       unsigned int err_mask, action;
+       const char *desc;
+} sil24_cerr_db[] = {
+       [0]                     = { AC_ERR_DEV, ATA_EH_REVALIDATE,
+                                   "device error" },
+       [PORT_CERR_DEV]         = { AC_ERR_DEV, ATA_EH_REVALIDATE,
+                                   "device error via D2H FIS" },
+       [PORT_CERR_SDB]         = { AC_ERR_DEV, ATA_EH_REVALIDATE,
+                                   "device error via SDB FIS" },
+       [PORT_CERR_DATA]        = { AC_ERR_ATA_BUS, ATA_EH_SOFTRESET,
+                                   "error in data FIS" },
+       [PORT_CERR_SEND]        = { AC_ERR_ATA_BUS, ATA_EH_SOFTRESET,
+                                   "failed to transmit command FIS" },
+       [PORT_CERR_INCONSISTENT] = { AC_ERR_HSM, ATA_EH_SOFTRESET,
+                                    "protocol mismatch" },
+       [PORT_CERR_DIRECTION]   = { AC_ERR_HSM, ATA_EH_SOFTRESET,
+                                   "data directon mismatch" },
+       [PORT_CERR_UNDERRUN]    = { AC_ERR_HSM, ATA_EH_SOFTRESET,
+                                   "ran out of SGEs while writing" },
+       [PORT_CERR_OVERRUN]     = { AC_ERR_HSM, ATA_EH_SOFTRESET,
+                                   "ran out of SGEs while reading" },
+       [PORT_CERR_PKT_PROT]    = { AC_ERR_HSM, ATA_EH_SOFTRESET,
+                                   "invalid data directon for ATAPI CDB" },
+       [PORT_CERR_SGT_BOUNDARY] = { AC_ERR_SYSTEM, ATA_EH_SOFTRESET,
+                                    "SGT no on qword boundary" },
+       [PORT_CERR_SGT_TGTABRT] = { AC_ERR_HOST_BUS, ATA_EH_SOFTRESET,
+                                   "PCI target abort while fetching SGT" },
+       [PORT_CERR_SGT_MSTABRT] = { AC_ERR_HOST_BUS, ATA_EH_SOFTRESET,
+                                   "PCI master abort while fetching SGT" },
+       [PORT_CERR_SGT_PCIPERR] = { AC_ERR_HOST_BUS, ATA_EH_SOFTRESET,
+                                   "PCI parity error while fetching SGT" },
+       [PORT_CERR_CMD_BOUNDARY] = { AC_ERR_SYSTEM, ATA_EH_SOFTRESET,
+                                    "PRB not on qword boundary" },
+       [PORT_CERR_CMD_TGTABRT] = { AC_ERR_HOST_BUS, ATA_EH_SOFTRESET,
+                                   "PCI target abort while fetching PRB" },
+       [PORT_CERR_CMD_MSTABRT] = { AC_ERR_HOST_BUS, ATA_EH_SOFTRESET,
+                                   "PCI master abort while fetching PRB" },
+       [PORT_CERR_CMD_PCIPERR] = { AC_ERR_HOST_BUS, ATA_EH_SOFTRESET,
+                                   "PCI parity error while fetching PRB" },
+       [PORT_CERR_XFR_UNDEF]   = { AC_ERR_HOST_BUS, ATA_EH_SOFTRESET,
+                                   "undefined error while transferring data" },
+       [PORT_CERR_XFR_TGTABRT] = { AC_ERR_HOST_BUS, ATA_EH_SOFTRESET,
+                                   "PCI target abort while transferring data" },
+       [PORT_CERR_XFR_MSTABRT] = { AC_ERR_HOST_BUS, ATA_EH_SOFTRESET,
+                                   "PCI master abort while transferring data" },
+       [PORT_CERR_XFR_PCIPERR] = { AC_ERR_HOST_BUS, ATA_EH_SOFTRESET,
+                                   "PCI parity error while transferring data" },
+       [PORT_CERR_SENDSERVICE] = { AC_ERR_HSM, ATA_EH_SOFTRESET,
+                                   "FIS received while sending service FIS" },
+};
+
 /*
  * ap->private_data
  *
@@ -253,8 +327,11 @@ static int sil24_probe_reset(struct ata_port *ap, unsigned int *classes);
 static void sil24_qc_prep(struct ata_queued_cmd *qc);
 static unsigned int sil24_qc_issue(struct ata_queued_cmd *qc);
 static void sil24_irq_clear(struct ata_port *ap);
-static void sil24_eng_timeout(struct ata_port *ap);
 static irqreturn_t sil24_interrupt(int irq, void *dev_instance, struct pt_regs *regs);
+static void sil24_freeze(struct ata_port *ap);
+static void sil24_thaw(struct ata_port *ap);
+static void sil24_error_handler(struct ata_port *ap);
+static void sil24_post_internal_cmd(struct ata_queued_cmd *qc);
 static int sil24_port_start(struct ata_port *ap);
 static void sil24_port_stop(struct ata_port *ap);
 static void sil24_host_stop(struct ata_host_set *host_set);
@@ -281,7 +358,8 @@ static struct scsi_host_template sil24_sht = {
        .name                   = DRV_NAME,
        .ioctl                  = ata_scsi_ioctl,
        .queuecommand           = ata_scsi_queuecmd,
-       .can_queue              = ATA_DEF_QUEUE,
+       .change_queue_depth     = ata_scsi_change_queue_depth,
+       .can_queue              = SIL24_MAX_CMDS,
        .this_id                = ATA_SHT_THIS_ID,
        .sg_tablesize           = LIBATA_MAX_PRD,
        .cmd_per_lun            = ATA_SHT_CMD_PER_LUN,
@@ -309,14 +387,17 @@ static const struct ata_port_operations sil24_ops = {
        .qc_prep                = sil24_qc_prep,
        .qc_issue               = sil24_qc_issue,
 
-       .eng_timeout            = sil24_eng_timeout,
-
        .irq_handler            = sil24_interrupt,
        .irq_clear              = sil24_irq_clear,
 
        .scr_read               = sil24_scr_read,
        .scr_write              = sil24_scr_write,
 
+       .freeze                 = sil24_freeze,
+       .thaw                   = sil24_thaw,
+       .error_handler          = sil24_error_handler,
+       .post_internal_cmd      = sil24_post_internal_cmd,
+
        .port_start             = sil24_port_start,
        .port_stop              = sil24_port_stop,
        .host_stop              = sil24_host_stop,
@@ -333,9 +414,8 @@ static struct ata_port_info sil24_port_info[] = {
        /* sil_3124 */
        {
                .sht            = &sil24_sht,
-               .host_flags     = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
-                                 ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA |
-                                 SIL24_NPORTS2FLAG(4),
+               .host_flags     = SIL24_COMMON_FLAGS | SIL24_NPORTS2FLAG(4) |
+                                 SIL24_FLAG_PCIX_IRQ_WOC,
                .pio_mask       = 0x1f,                 /* pio0-4 */
                .mwdma_mask     = 0x07,                 /* mwdma0-2 */
                .udma_mask      = 0x3f,                 /* udma0-5 */
@@ -344,9 +424,7 @@ static struct ata_port_info sil24_port_info[] = {
        /* sil_3132 */
        {
                .sht            = &sil24_sht,
-               .host_flags     = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
-                                 ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA |
-                                 SIL24_NPORTS2FLAG(2),
+               .host_flags     = SIL24_COMMON_FLAGS | SIL24_NPORTS2FLAG(2),
                .pio_mask       = 0x1f,                 /* pio0-4 */
                .mwdma_mask     = 0x07,                 /* mwdma0-2 */
                .udma_mask      = 0x3f,                 /* udma0-5 */
@@ -355,9 +433,7 @@ static struct ata_port_info sil24_port_info[] = {
        /* sil_3131/sil_3531 */
        {
                .sht            = &sil24_sht,
-               .host_flags     = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
-                                 ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA |
-                                 SIL24_NPORTS2FLAG(1),
+               .host_flags     = SIL24_COMMON_FLAGS | SIL24_NPORTS2FLAG(1),
                .pio_mask       = 0x1f,                 /* pio0-4 */
                .mwdma_mask     = 0x07,                 /* mwdma0-2 */
                .udma_mask      = 0x3f,                 /* udma0-5 */
@@ -365,6 +441,13 @@ static struct ata_port_info sil24_port_info[] = {
        },
 };
 
+static int sil24_tag(int tag)
+{
+       if (unlikely(ata_tag_internal(tag)))
+               return 0;
+       return tag;
+}
+
 static void sil24_dev_config(struct ata_port *ap, struct ata_device *dev)
 {
        void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr;
@@ -426,56 +509,65 @@ static void sil24_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
        *tf = pp->tf;
 }
 
-static int sil24_softreset(struct ata_port *ap, int verbose,
-                          unsigned int *class)
+static int sil24_init_port(struct ata_port *ap)
+{
+       void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr;
+       u32 tmp;
+
+       writel(PORT_CS_INIT, port + PORT_CTRL_STAT);
+       ata_wait_register(port + PORT_CTRL_STAT,
+                         PORT_CS_INIT, PORT_CS_INIT, 10, 100);
+       tmp = ata_wait_register(port + PORT_CTRL_STAT,
+                               PORT_CS_RDY, 0, 10, 100);
+
+       if ((tmp & (PORT_CS_INIT | PORT_CS_RDY)) != PORT_CS_RDY)
+               return -EIO;
+       return 0;
+}
+
+static int sil24_softreset(struct ata_port *ap, unsigned int *class)
 {
        void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr;
        struct sil24_port_priv *pp = ap->private_data;
        struct sil24_prb *prb = &pp->cmd_block[0].ata.prb;
        dma_addr_t paddr = pp->cmd_block_dma;
-       unsigned long timeout = jiffies + ATA_TMOUT_BOOT * HZ;
-       u32 irq_enable, irq_stat;
+       u32 mask, irq_stat;
+       const char *reason;
 
        DPRINTK("ENTER\n");
 
-       if (!sata_dev_present(ap)) {
+       if (ata_port_offline(ap)) {
                DPRINTK("PHY reports no device\n");
                *class = ATA_DEV_NONE;
                goto out;
        }
 
-       /* temporarily turn off IRQs during SRST */
-       irq_enable = readl(port + PORT_IRQ_ENABLE_SET);
-       writel(irq_enable, port + PORT_IRQ_ENABLE_CLR);
-
-       /*
-        * XXX: Not sure whether the following sleep is needed or not.
-        * The original driver had it.  So....
-        */
-       msleep(10);
+       /* put the port into known state */
+       if (sil24_init_port(ap)) {
+               reason ="port not ready";
+               goto err;
+       }
 
-       prb->ctrl = PRB_CTRL_SRST;
+       /* do SRST */
+       prb->ctrl = cpu_to_le16(PRB_CTRL_SRST);
        prb->fis[1] = 0; /* no PM yet */
 
        writel((u32)paddr, port + PORT_CMD_ACTIVATE);
+       writel((u64)paddr >> 32, port + PORT_CMD_ACTIVATE + 4);
 
-       do {
-               irq_stat = readl(port + PORT_IRQ_STAT);
-               writel(irq_stat, port + PORT_IRQ_STAT);         /* clear irq */
+       mask = (PORT_IRQ_COMPLETE | PORT_IRQ_ERROR) << PORT_IRQ_RAW_SHIFT;
+       irq_stat = ata_wait_register(port + PORT_IRQ_STAT, mask, 0x0,
+                                    100, ATA_TMOUT_BOOT / HZ * 1000);
 
-               irq_stat >>= PORT_IRQ_RAW_SHIFT;
-               if (irq_stat & (PORT_IRQ_COMPLETE | PORT_IRQ_ERROR))
-                       break;
-
-               msleep(100);
-       } while (time_before(jiffies, timeout));
-
-       /* restore IRQs */
-       writel(irq_enable, port + PORT_IRQ_ENABLE_SET);
+       writel(irq_stat, port + PORT_IRQ_STAT); /* clear IRQs */
+       irq_stat >>= PORT_IRQ_RAW_SHIFT;
 
        if (!(irq_stat & PORT_IRQ_COMPLETE)) {
-               DPRINTK("EXIT, srst failed\n");
-               return -EIO;
+               if (irq_stat & PORT_IRQ_ERROR)
+                       reason = "SRST command error";
+               else
+                       reason = "timeout";
+               goto err;
        }
 
        sil24_update_tf(ap);
@@ -487,15 +579,55 @@ static int sil24_softreset(struct ata_port *ap, int verbose,
  out:
        DPRINTK("EXIT, class=%u\n", *class);
        return 0;
+
+ err:
+       ata_port_printk(ap, KERN_ERR, "softreset failed (%s)\n", reason);
+       return -EIO;
 }
 
-static int sil24_hardreset(struct ata_port *ap, int verbose,
-                          unsigned int *class)
+static int sil24_hardreset(struct ata_port *ap, unsigned int *class)
 {
-       unsigned int dummy_class;
+       void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr;
+       const char *reason;
+       int tout_msec;
+       u32 tmp;
+
+       /* sil24 does the right thing(tm) without any protection */
+       sata_set_spd(ap);
+
+       tout_msec = 100;
+       if (ata_port_online(ap))
+               tout_msec = 5000;
 
-       /* sil24 doesn't report device signature after hard reset */
-       return sata_std_hardreset(ap, verbose, &dummy_class);
+       writel(PORT_CS_DEV_RST, port + PORT_CTRL_STAT);
+       tmp = ata_wait_register(port + PORT_CTRL_STAT,
+                               PORT_CS_DEV_RST, PORT_CS_DEV_RST, 10, tout_msec);
+
+       /* SStatus oscillates between zero and valid status for short
+        * duration after DEV_RST, give it time to settle.
+        */
+       msleep(100);
+
+       if (tmp & PORT_CS_DEV_RST) {
+               if (ata_port_offline(ap))
+                       return 0;
+               reason = "link not ready";
+               goto err;
+       }
+
+       if (ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT)) {
+               reason = "device not ready";
+               goto err;
+       }
+
+       /* sil24 doesn't report device class code after hardreset,
+        * leave *class alone.
+        */
+       return 0;
+
+ err:
+       ata_port_printk(ap, KERN_ERR, "hardreset failed (%s)\n", reason);
+       return -EIO;
 }
 
 static int sil24_probe_reset(struct ata_port *ap, unsigned int *classes)
@@ -528,17 +660,20 @@ static void sil24_qc_prep(struct ata_queued_cmd *qc)
 {
        struct ata_port *ap = qc->ap;
        struct sil24_port_priv *pp = ap->private_data;
-       union sil24_cmd_block *cb = pp->cmd_block + qc->tag;
+       union sil24_cmd_block *cb;
        struct sil24_prb *prb;
        struct sil24_sge *sge;
+       u16 ctrl = 0;
+
+       cb = &pp->cmd_block[sil24_tag(qc->tag)];
 
        switch (qc->tf.protocol) {
        case ATA_PROT_PIO:
        case ATA_PROT_DMA:
+       case ATA_PROT_NCQ:
        case ATA_PROT_NODATA:
                prb = &cb->ata.prb;
                sge = cb->ata.sge;
-               prb->ctrl = 0;
                break;
 
        case ATA_PROT_ATAPI:
@@ -551,12 +686,10 @@ static void sil24_qc_prep(struct ata_queued_cmd *qc)
 
                if (qc->tf.protocol != ATA_PROT_ATAPI_NODATA) {
                        if (qc->tf.flags & ATA_TFLAG_WRITE)
-                               prb->ctrl = PRB_CTRL_PACKET_WRITE;
+                               ctrl = PRB_CTRL_PACKET_WRITE;
                        else
-                               prb->ctrl = PRB_CTRL_PACKET_READ;
-               } else
-                       prb->ctrl = 0;
-
+                               ctrl = PRB_CTRL_PACKET_READ;
+               }
                break;
 
        default:
@@ -565,6 +698,7 @@ static void sil24_qc_prep(struct ata_queued_cmd *qc)
                BUG();
        }
 
+       prb->ctrl = cpu_to_le16(ctrl);
        ata_tf_to_fis(&qc->tf, prb->fis, 0);
 
        if (qc->flags & ATA_QCFLAG_DMAMAP)
@@ -574,11 +708,18 @@ static void sil24_qc_prep(struct ata_queued_cmd *qc)
 static unsigned int sil24_qc_issue(struct ata_queued_cmd *qc)
 {
        struct ata_port *ap = qc->ap;
-       void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr;
        struct sil24_port_priv *pp = ap->private_data;
-       dma_addr_t paddr = pp->cmd_block_dma + qc->tag * sizeof(*pp->cmd_block);
+       void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr;
+       unsigned int tag = sil24_tag(qc->tag);
+       dma_addr_t paddr;
+       void __iomem *activate;
+
+       paddr = pp->cmd_block_dma + tag * sizeof(*pp->cmd_block);
+       activate = port + PORT_CMD_ACTIVATE + tag * 8;
+
+       writel((u32)paddr, activate);
+       writel((u64)paddr >> 32, activate + 4);
 
-       writel((u32)paddr, port + PORT_CMD_ACTIVATE);
        return 0;
 }
 
@@ -587,162 +728,141 @@ static void sil24_irq_clear(struct ata_port *ap)
        /* unused */
 }
 
-static int __sil24_restart_controller(void __iomem *port)
+static void sil24_freeze(struct ata_port *ap)
 {
-       u32 tmp;
-       int cnt;
-
-       writel(PORT_CS_INIT, port + PORT_CTRL_STAT);
-
-       /* Max ~10ms */
-       for (cnt = 0; cnt < 10000; cnt++) {
-               tmp = readl(port + PORT_CTRL_STAT);
-               if (tmp & PORT_CS_RDY)
-                       return 0;
-               udelay(1);
-       }
+       void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr;
 
-       return -1;
+       /* Port-wide IRQ mask in HOST_CTRL doesn't really work, clear
+        * PORT_IRQ_ENABLE instead.
+        */
+       writel(0xffff, port + PORT_IRQ_ENABLE_CLR);
 }
 
-static void sil24_restart_controller(struct ata_port *ap)
+static void sil24_thaw(struct ata_port *ap)
 {
-       if (__sil24_restart_controller((void __iomem *)ap->ioaddr.cmd_addr))
-               printk(KERN_ERR DRV_NAME
-                      " ata%u: failed to restart controller\n", ap->id);
+       void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr;
+       u32 tmp;
+
+       /* clear IRQ */
+       tmp = readl(port + PORT_IRQ_STAT);
+       writel(tmp, port + PORT_IRQ_STAT);
+
+       /* turn IRQ back on */
+       writel(DEF_PORT_IRQ, port + PORT_IRQ_ENABLE_SET);
 }
 
-static int __sil24_reset_controller(void __iomem *port)
+static void sil24_error_intr(struct ata_port *ap)
 {
-       int cnt;
-       u32 tmp;
+       void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr;
+       struct ata_eh_info *ehi = &ap->eh_info;
+       int freeze = 0;
+       u32 irq_stat;
 
-       /* Reset controller state.  Is this correct? */
-       writel(PORT_CS_DEV_RST, port + PORT_CTRL_STAT);
-       readl(port + PORT_CTRL_STAT);   /* sync */
+       /* on error, we need to clear IRQ explicitly */
+       irq_stat = readl(port + PORT_IRQ_STAT);
+       writel(irq_stat, port + PORT_IRQ_STAT);
 
-       /* Max ~100ms */
-       for (cnt = 0; cnt < 1000; cnt++) {
-               udelay(100);
-               tmp = readl(port + PORT_CTRL_STAT);
-               if (!(tmp & PORT_CS_DEV_RST))
-                       break;
-       }
+       /* first, analyze and record host port events */
+       ata_ehi_clear_desc(ehi);
 
-       if (tmp & PORT_CS_DEV_RST)
-               return -1;
+       ata_ehi_push_desc(ehi, "irq_stat 0x%08x", irq_stat);
 
-       if (tmp & PORT_CS_RDY)
-               return 0;
+       if (irq_stat & PORT_IRQ_DEV_XCHG) {
+               ehi->err_mask |= AC_ERR_ATA_BUS;
+               /* sil24 doesn't recover very well from phy
+                * disconnection with a softreset.  Force hardreset.
+                */
+               ehi->action |= ATA_EH_HARDRESET;
+               ata_ehi_push_desc(ehi, ", device_exchanged");
+               freeze = 1;
+       }
 
-       return __sil24_restart_controller(port);
-}
+       if (irq_stat & PORT_IRQ_UNK_FIS) {
+               ehi->err_mask |= AC_ERR_HSM;
+               ehi->action |= ATA_EH_SOFTRESET;
+               ata_ehi_push_desc(ehi , ", unknown FIS");
+               freeze = 1;
+       }
 
-static void sil24_reset_controller(struct ata_port *ap)
-{
-       printk(KERN_NOTICE DRV_NAME
-              " ata%u: resetting controller...\n", ap->id);
-       if (__sil24_reset_controller((void __iomem *)ap->ioaddr.cmd_addr))
-                printk(KERN_ERR DRV_NAME
-                       " ata%u: failed to reset controller\n", ap->id);
-}
+       /* deal with command error */
+       if (irq_stat & PORT_IRQ_ERROR) {
+               struct sil24_cerr_info *ci = NULL;
+               unsigned int err_mask = 0, action = 0;
+               struct ata_queued_cmd *qc;
+               u32 cerr;
+
+               /* analyze CMD_ERR */
+               cerr = readl(port + PORT_CMD_ERR);
+               if (cerr < ARRAY_SIZE(sil24_cerr_db))
+                       ci = &sil24_cerr_db[cerr];
+
+               if (ci && ci->desc) {
+                       err_mask |= ci->err_mask;
+                       action |= ci->action;
+                       ata_ehi_push_desc(ehi, ", %s", ci->desc);
+               } else {
+                       err_mask |= AC_ERR_OTHER;
+                       action |= ATA_EH_SOFTRESET;
+                       ata_ehi_push_desc(ehi, ", unknown command error %d",
+                                         cerr);
+               }
 
-static void sil24_eng_timeout(struct ata_port *ap)
-{
-       struct ata_queued_cmd *qc;
+               /* record error info */
+               qc = ata_qc_from_tag(ap, ap->active_tag);
+               if (qc) {
+                       sil24_update_tf(ap);
+                       qc->err_mask |= err_mask;
+               } else
+                       ehi->err_mask |= err_mask;
 
-       qc = ata_qc_from_tag(ap, ap->active_tag);
+               ehi->action |= action;
+       }
 
-       printk(KERN_ERR "ata%u: command timeout\n", ap->id);
-       qc->err_mask |= AC_ERR_TIMEOUT;
-       ata_eh_qc_complete(qc);
+       /* freeze or abort */
+       if (freeze)
+               ata_port_freeze(ap);
+       else
+               ata_port_abort(ap);
+}
 
-       sil24_reset_controller(ap);
+static void sil24_finish_qc(struct ata_queued_cmd *qc)
+{
+       if (qc->flags & ATA_QCFLAG_RESULT_TF)
+               sil24_update_tf(qc->ap);
 }
 
-static void sil24_error_intr(struct ata_port *ap, u32 slot_stat)
+static inline void sil24_host_intr(struct ata_port *ap)
 {
-       struct ata_queued_cmd *qc = ata_qc_from_tag(ap, ap->active_tag);
-       struct sil24_port_priv *pp = ap->private_data;
        void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr;
-       u32 irq_stat, cmd_err, sstatus, serror;
-       unsigned int err_mask;
+       u32 slot_stat, qc_active;
+       int rc;
 
-       irq_stat = readl(port + PORT_IRQ_STAT);
-       writel(irq_stat, port + PORT_IRQ_STAT);         /* clear irq */
+       slot_stat = readl(port + PORT_SLOT_STAT);
 
-       if (!(irq_stat & PORT_IRQ_ERROR)) {
-               /* ignore non-completion, non-error irqs for now */
-               printk(KERN_WARNING DRV_NAME
-                      "ata%u: non-error exception irq (irq_stat %x)\n",
-                      ap->id, irq_stat);
+       if (unlikely(slot_stat & HOST_SSTAT_ATTN)) {
+               sil24_error_intr(ap);
                return;
        }
 
-       cmd_err = readl(port + PORT_CMD_ERR);
-       sstatus = readl(port + PORT_SSTATUS);
-       serror = readl(port + PORT_SERROR);
-       if (serror)
-               writel(serror, port + PORT_SERROR);
+       if (ap->flags & SIL24_FLAG_PCIX_IRQ_WOC)
+               writel(PORT_IRQ_COMPLETE, port + PORT_IRQ_STAT);
 
-       /*
-        * Don't log ATAPI device errors.  They're supposed to happen
-        * and any serious errors will be logged using sense data by
-        * the SCSI layer.
-        */
-       if (ap->device[0].class != ATA_DEV_ATAPI || cmd_err > PORT_CERR_SDB)
-               printk("ata%u: error interrupt on port%d\n"
-                      "  stat=0x%x irq=0x%x cmd_err=%d sstatus=0x%x serror=0x%x\n",
-                      ap->id, ap->port_no, slot_stat, irq_stat, cmd_err, sstatus, serror);
-
-       if (cmd_err == PORT_CERR_DEV || cmd_err == PORT_CERR_SDB) {
-               /*
-                * Device is reporting error, tf registers are valid.
-                */
-               sil24_update_tf(ap);
-               err_mask = ac_err_mask(pp->tf.command);
-               sil24_restart_controller(ap);
-       } else {
-               /*
-                * Other errors.  libata currently doesn't have any
-                * mechanism to report these errors.  Just turn on
-                * ATA_ERR.
-                */
-               err_mask = AC_ERR_OTHER;
-               sil24_reset_controller(ap);
+       qc_active = slot_stat & ~HOST_SSTAT_ATTN;
+       rc = ata_qc_complete_multiple(ap, qc_active, sil24_finish_qc);
+       if (rc > 0)
+               return;
+       if (rc < 0) {
+               struct ata_eh_info *ehi = &ap->eh_info;
+               ehi->err_mask |= AC_ERR_HSM;
+               ehi->action |= ATA_EH_SOFTRESET;
+               ata_port_freeze(ap);
+               return;
        }
 
-       if (qc) {
-               qc->err_mask |= err_mask;
-               ata_qc_complete(qc);
-       }
-}
-
-static inline void sil24_host_intr(struct ata_port *ap)
-{
-       struct ata_queued_cmd *qc = ata_qc_from_tag(ap, ap->active_tag);
-       void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr;
-       u32 slot_stat;
-
-       slot_stat = readl(port + PORT_SLOT_STAT);
-       if (!(slot_stat & HOST_SSTAT_ATTN)) {
-               struct sil24_port_priv *pp = ap->private_data;
-               /*
-                * !HOST_SSAT_ATTN guarantees successful completion,
-                * so reading back tf registers is unnecessary for
-                * most commands.  TODO: read tf registers for
-                * commands which require these values on successful
-                * completion (EXECUTE DEVICE DIAGNOSTIC, CHECK POWER,
-                * DEVICE RESET and READ PORT MULTIPLIER (any more?).
-                */
-               sil24_update_tf(ap);
-
-               if (qc) {
-                       qc->err_mask |= ac_err_mask(pp->tf.command);
-                       ata_qc_complete(qc);
-               }
-       } else
-               sil24_error_intr(ap, slot_stat);
+       if (ata_ratelimit())
+               ata_port_printk(ap, KERN_INFO, "spurious interrupt "
+                       "(slot_stat 0x%x active_tag %d sactive 0x%x)\n",
+                       slot_stat, ap->active_tag, ap->sactive);
 }
 
 static irqreturn_t sil24_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
@@ -769,7 +889,7 @@ static irqreturn_t sil24_interrupt(int irq, void *dev_instance, struct pt_regs *
        for (i = 0; i < host_set->n_ports; i++)
                if (status & (1 << i)) {
                        struct ata_port *ap = host_set->ports[i];
-                       if (ap && !(ap->flags & ATA_FLAG_PORT_DISABLED)) {
+                       if (ap && !(ap->flags & ATA_FLAG_DISABLED)) {
                                sil24_host_intr(host_set->ports[i]);
                                handled++;
                        } else
@@ -782,9 +902,34 @@ static irqreturn_t sil24_interrupt(int irq, void *dev_instance, struct pt_regs *
        return IRQ_RETVAL(handled);
 }
 
+static void sil24_error_handler(struct ata_port *ap)
+{
+       struct ata_eh_context *ehc = &ap->eh_context;
+
+       if (sil24_init_port(ap)) {
+               ata_eh_freeze_port(ap);
+               ehc->i.action |= ATA_EH_HARDRESET;
+       }
+
+       /* perform recovery */
+       ata_do_eh(ap, sil24_softreset, sil24_hardreset, ata_std_postreset);
+}
+
+static void sil24_post_internal_cmd(struct ata_queued_cmd *qc)
+{
+       struct ata_port *ap = qc->ap;
+
+       if (qc->flags & ATA_QCFLAG_FAILED)
+               qc->err_mask |= AC_ERR_OTHER;
+
+       /* make DMA engine forget about the failed command */
+       if (qc->err_mask)
+               sil24_init_port(ap);
+}
+
 static inline void sil24_cblk_free(struct sil24_port_priv *pp, struct device *dev)
 {
-       const size_t cb_size = sizeof(*pp->cmd_block);
+       const size_t cb_size = sizeof(*pp->cmd_block) * SIL24_MAX_CMDS;
 
        dma_free_coherent(dev, cb_size, pp->cmd_block, pp->cmd_block_dma);
 }
@@ -794,7 +939,7 @@ static int sil24_port_start(struct ata_port *ap)
        struct device *dev = ap->host_set->dev;
        struct sil24_port_priv *pp;
        union sil24_cmd_block *cb;
-       size_t cb_size = sizeof(*cb);
+       size_t cb_size = sizeof(*cb) * SIL24_MAX_CMDS;
        dma_addr_t cb_dma;
        int rc = -ENOMEM;
 
@@ -858,6 +1003,7 @@ static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
        void __iomem *host_base = NULL;
        void __iomem *port_base = NULL;
        int i, rc;
+       u32 tmp;
 
        if (!printed_version++)
                dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
@@ -910,35 +1056,51 @@ static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
        /*
         * Configure the device
         */
-       /*
-        * FIXME: This device is certainly 64-bit capable.  We just
-        * don't know how to use it.  After fixing 32bit activation in
-        * this function, enable 64bit masks here.
-        */
-       rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
-       if (rc) {
-               dev_printk(KERN_ERR, &pdev->dev,
-                          "32-bit DMA enable failed\n");
-               goto out_free;
-       }
-       rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
-       if (rc) {
-               dev_printk(KERN_ERR, &pdev->dev,
-                          "32-bit consistent DMA enable failed\n");
-               goto out_free;
+       if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK)) {
+               rc = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK);
+               if (rc) {
+                       rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
+                       if (rc) {
+                               dev_printk(KERN_ERR, &pdev->dev,
+                                          "64-bit DMA enable failed\n");
+                               goto out_free;
+                       }
+               }
+       } else {
+               rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
+               if (rc) {
+                       dev_printk(KERN_ERR, &pdev->dev,
+                                  "32-bit DMA enable failed\n");
+                       goto out_free;
+               }
+               rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
+               if (rc) {
+                       dev_printk(KERN_ERR, &pdev->dev,
+                                  "32-bit consistent DMA enable failed\n");
+                       goto out_free;
+               }
        }
 
        /* GPIO off */
        writel(0, host_base + HOST_FLASH_CMD);
 
-       /* Mask interrupts during initialization */
+       /* Apply workaround for completion IRQ loss on PCI-X errata */
+       if (probe_ent->host_flags & SIL24_FLAG_PCIX_IRQ_WOC) {
+               tmp = readl(host_base + HOST_CTRL);
+               if (tmp & (HOST_CTRL_TRDY | HOST_CTRL_STOP | HOST_CTRL_DEVSEL))
+                       dev_printk(KERN_INFO, &pdev->dev,
+                                  "Applying completion IRQ loss on PCI-X "
+                                  "errata fix\n");
+               else
+                       probe_ent->host_flags &= ~SIL24_FLAG_PCIX_IRQ_WOC;
+       }
+
+       /* clear global reset & mask interrupts during initialization */
        writel(0, host_base + HOST_CTRL);
 
        for (i = 0; i < probe_ent->n_ports; i++) {
                void __iomem *port = port_base + i * PORT_REGS_SIZE;
                unsigned long portu = (unsigned long)port;
-               u32 tmp;
-               int cnt;
 
                probe_ent->port[i].cmd_addr = portu + PORT_PRB;
                probe_ent->port[i].scr_addr = portu + PORT_SCONTROL;
@@ -952,18 +1114,20 @@ static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
                tmp = readl(port + PORT_CTRL_STAT);
                if (tmp & PORT_CS_PORT_RST) {
                        writel(PORT_CS_PORT_RST, port + PORT_CTRL_CLR);
-                       readl(port + PORT_CTRL_STAT);   /* sync */
-                       for (cnt = 0; cnt < 10; cnt++) {
-                               msleep(10);
-                               tmp = readl(port + PORT_CTRL_STAT);
-                               if (!(tmp & PORT_CS_PORT_RST))
-                                       break;
-                       }
+                       tmp = ata_wait_register(port + PORT_CTRL_STAT,
+                                               PORT_CS_PORT_RST,
+                                               PORT_CS_PORT_RST, 10, 100);
                        if (tmp & PORT_CS_PORT_RST)
                                dev_printk(KERN_ERR, &pdev->dev,
                                           "failed to clear port RST\n");
                }
 
+               /* Configure IRQ WoC */
+               if (probe_ent->host_flags & SIL24_FLAG_PCIX_IRQ_WOC)
+                       writel(PORT_CS_IRQ_WOC, port + PORT_CTRL_STAT);
+               else
+                       writel(PORT_CS_IRQ_WOC, port + PORT_CTRL_CLR);
+
                /* Zero error counters. */
                writel(0x8000, port + PORT_DECODE_ERR_THRESH);
                writel(0x8000, port + PORT_CRC_ERR_THRESH);
@@ -972,26 +1136,11 @@ static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
                writel(0x0000, port + PORT_CRC_ERR_CNT);
                writel(0x0000, port + PORT_HSHK_ERR_CNT);
 
-               /* FIXME: 32bit activation? */
-               writel(0, port + PORT_ACTIVATE_UPPER_ADDR);
-               writel(PORT_CS_32BIT_ACTV, port + PORT_CTRL_STAT);
-
-               /* Configure interrupts */
-               writel(0xffff, port + PORT_IRQ_ENABLE_CLR);
-               writel(PORT_IRQ_COMPLETE | PORT_IRQ_ERROR | PORT_IRQ_SDB_FIS,
-                      port + PORT_IRQ_ENABLE_SET);
-
-               /* Clear interrupts */
-               writel(0x0fff0fff, port + PORT_IRQ_STAT);
-               writel(PORT_CS_IRQ_WOC, port + PORT_CTRL_CLR);
+               /* Always use 64bit activation */
+               writel(PORT_CS_32BIT_ACTV, port + PORT_CTRL_CLR);
 
                /* Clear port multiplier enable and resume bits */
                writel(PORT_CS_PM_EN | PORT_CS_RESUME, port + PORT_CTRL_CLR);
-
-               /* Reset itself */
-               if (__sil24_reset_controller(port))
-                       dev_printk(KERN_ERR, &pdev->dev,
-                                  "failed to reset controller\n");
        }
 
        /* Turn on interrupts */
index 728530d..3097821 100644 (file)
@@ -43,7 +43,7 @@
 #include <linux/libata.h>
 
 #define DRV_NAME       "sata_sis"
-#define DRV_VERSION    "0.5"
+#define DRV_VERSION    "0.6"
 
 enum {
        sis_180                 = 0,
index 53b0d5c..d5eb537 100644 (file)
@@ -54,7 +54,7 @@
 #endif /* CONFIG_PPC_OF */
 
 #define DRV_NAME       "sata_svw"
-#define DRV_VERSION    "1.07"
+#define DRV_VERSION    "1.8"
 
 enum {
        /* Taskfile registers offsets */
@@ -257,7 +257,7 @@ static int k2_sata_proc_info(struct Scsi_Host *shost, char *page, char **start,
        int len, index;
 
        /* Find  the ata_port */
-       ap = (struct ata_port *) &shost->hostdata[0];
+       ap = ata_shost_to_port(shost);
        if (ap == NULL)
                return 0;
 
index 4139ad4..70a6954 100644 (file)
@@ -46,7 +46,7 @@
 #include "sata_promise.h"
 
 #define DRV_NAME       "sata_sx4"
-#define DRV_VERSION    "0.8"
+#define DRV_VERSION    "0.9"
 
 
 enum {
@@ -218,7 +218,7 @@ static const struct ata_port_info pdc_port_info[] = {
                .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 @@ static irqreturn_t pdc20621_interrupt (int irq, void *dev_instance, struct pt_re
                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_PORT_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,15 +868,16 @@ static void pdc_eng_timeout(struct ata_port *ap)
        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;
@@ -1375,10 +1376,6 @@ static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *
        if (!printed_version++)
                dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
 
-       /*
-        * If this driver happens to only be useful on Apple's K2, then
-        * we should check that here as it has a normal Serverworks ID
-        */
        rc = pci_enable_device(pdev);
        if (rc)
                return rc;
index 38b52bd..15f81bf 100644 (file)
@@ -37,7 +37,7 @@
 #include <linux/libata.h>
 
 #define DRV_NAME       "sata_uli"
-#define DRV_VERSION    "0.5"
+#define DRV_VERSION    "0.6"
 
 enum {
        uli_5289                = 0,
index 9e7ae4e..17aefab 100644 (file)
@@ -47,7 +47,7 @@
 #include <asm/io.h>
 
 #define DRV_NAME       "sata_via"
-#define DRV_VERSION    "1.1"
+#define DRV_VERSION    "1.2"
 
 enum board_ids_enum {
        vt6420,
index 8a29ce3..0372be7 100644 (file)
@@ -221,14 +221,21 @@ static irqreturn_t vsc_sata_interrupt (int irq, void *dev_instance,
 
                        ap = host_set->ports[i];
 
-                       if (ap && !(ap->flags &
-                                   (ATA_FLAG_PORT_DISABLED|ATA_FLAG_NOINTR))) {
+                       if (is_vsc_sata_int_err(i, int_status)) {
+                               u32 err_status;
+                               printk(KERN_DEBUG "%s: ignoring interrupt(s)\n", __FUNCTION__);
+                               err_status = ap ? vsc_sata_scr_read(ap, SCR_ERROR) : 0;
+                               vsc_sata_scr_write(ap, SCR_ERROR, err_status);
+                               handled++;
+                       }
+
+                       if (ap && !(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 += ata_host_intr(ap, qc);
-                               else if (is_vsc_sata_int_err(i, int_status)) {
+                               else if (is_vsc_sata_int_err(i, int_status)) {
                                        /*
                                         * On some chips (i.e. Intel 31244), an error
                                         * interrupt will sneak in at initialization
index 73994e2..dae4f08 100644 (file)
@@ -719,6 +719,24 @@ void scsi_init_cmd_from_req(struct scsi_cmnd *cmd, struct scsi_request *sreq)
  */
 static DEFINE_PER_CPU(struct list_head, scsi_done_q);
 
+/**
+ * scsi_req_abort_cmd -- Request command recovery for the specified command
+ * cmd: pointer to the SCSI command of interest
+ *
+ * This function requests that SCSI Core start recovery for the
+ * command by deleting the timer and adding the command to the eh
+ * queue.  It can be called by either LLDDs or SCSI Core.  LLDDs who
+ * implement their own error recovery MAY ignore the timeout event if
+ * they generated scsi_req_abort_cmd.
+ */
+void scsi_req_abort_cmd(struct scsi_cmnd *cmd)
+{
+       if (!scsi_delete_timer(cmd))
+               return;
+       scsi_times_out(cmd);
+}
+EXPORT_SYMBOL(scsi_req_abort_cmd);
+
 /**
  * scsi_done - Enqueue the finished SCSI command into the done queue.
  * @cmd: The SCSI Command for which a low-level device driver (LLDD) gives
index 1c75646..346ab72 100644 (file)
@@ -57,6 +57,28 @@ void scsi_eh_wakeup(struct Scsi_Host *shost)
        }
 }
 
+/**
+ * scsi_schedule_eh - schedule EH for SCSI host
+ * @shost:     SCSI host to invoke error handling on.
+ *
+ * Schedule SCSI EH without scmd.
+ **/
+void scsi_schedule_eh(struct Scsi_Host *shost)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(shost->host_lock, flags);
+
+       if (scsi_host_set_state(shost, SHOST_RECOVERY) == 0 ||
+           scsi_host_set_state(shost, SHOST_CANCEL_RECOVERY) == 0) {
+               shost->host_eh_scheduled++;
+               scsi_eh_wakeup(shost);
+       }
+
+       spin_unlock_irqrestore(shost->host_lock, flags);
+}
+EXPORT_SYMBOL_GPL(scsi_schedule_eh);
+
 /**
  * scsi_eh_scmd_add - add scsi cmd to error handling.
  * @scmd:      scmd to run eh on.
@@ -1517,7 +1539,7 @@ int scsi_error_handler(void *data)
         */
        set_current_state(TASK_INTERRUPTIBLE);
        while (!kthread_should_stop()) {
-               if (shost->host_failed == 0 ||
+               if ((shost->host_failed == 0 && shost->host_eh_scheduled == 0) ||
                    shost->host_failed != shost->host_busy) {
                        SCSI_LOG_ERROR_RECOVERY(1,
                                printk("Error handler scsi_eh_%d sleeping\n",
index 764a8b3..18e3477 100644 (file)
@@ -566,7 +566,7 @@ void scsi_device_unbusy(struct scsi_device *sdev)
        spin_lock_irqsave(shost->host_lock, flags);
        shost->host_busy--;
        if (unlikely(scsi_host_in_recovery(shost) &&
-                    shost->host_failed))
+                    (shost->host_failed || shost->host_eh_scheduled)))
                scsi_eh_wakeup(shost);
        spin_unlock(shost->host_lock);
        spin_lock(sdev->request_queue->queue_lock);
diff --git a/drivers/scsi/scsi_transport_api.h b/drivers/scsi/scsi_transport_api.h
new file mode 100644 (file)
index 0000000..934f0e6
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef _SCSI_TRANSPORT_API_H
+#define _SCSI_TRANSPORT_API_H
+
+void scsi_schedule_eh(struct Scsi_Host *shost);
+
+#endif /* _SCSI_TRANSPORT_API_H */
index 312a2c0..c494e1c 100644 (file)
@@ -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 */
@@ -130,6 +133,8 @@ enum {
        ATA_CMD_WRITE           = 0xCA,
        ATA_CMD_WRITE_EXT       = 0x35,
        ATA_CMD_WRITE_FUA_EXT   = 0x3D,
+       ATA_CMD_FPDMA_READ      = 0x60,
+       ATA_CMD_FPDMA_WRITE     = 0x61,
        ATA_CMD_PIO_READ        = 0x20,
        ATA_CMD_PIO_READ_EXT    = 0x24,
        ATA_CMD_PIO_WRITE       = 0x30,
@@ -148,6 +153,10 @@ enum {
        ATA_CMD_INIT_DEV_PARAMS = 0x91,
        ATA_CMD_READ_NATIVE_MAX = 0xF8,
        ATA_CMD_READ_NATIVE_MAX_EXT = 0x27,
+       ATA_CMD_READ_LOG_EXT    = 0x2f,
+
+       /* READ_LOG_EXT pages */
+       ATA_LOG_SATA_NCQ        = 0x10,
 
        /* SETFEATURES stuff */
        SETFEATURES_XFER        = 0x03,
@@ -192,6 +201,16 @@ enum {
        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 */
@@ -199,6 +218,7 @@ enum {
        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 {
@@ -207,6 +227,7 @@ enum ata_tf_protocols {
        ATA_PROT_NODATA,        /* no data */
        ATA_PROT_PIO,           /* PIO single sector */
        ATA_PROT_DMA,           /* DMA */
+       ATA_PROT_NCQ,           /* NCQ */
        ATA_PROT_ATAPI,         /* packet command, PIO data xfer*/
        ATA_PROT_ATAPI_NODATA,  /* packet command, no data */
        ATA_PROT_ATAPI_DMA,     /* packet command with special DMA sauce */
@@ -262,6 +283,8 @@ struct ata_taskfile {
 #define ata_id_has_pm(id)      ((id)[82] & (1 << 3))
 #define ata_id_has_lba(id)     ((id)[49] & (1 << 9))
 #define ata_id_has_dma(id)     ((id)[49] & (1 << 8))
+#define ata_id_has_ncq(id)     ((id)[76] & (1 << 8))
+#define ata_id_queue_depth(id) (((id)[75] & 0x1f) + 1)
 #define ata_id_removeable(id)  ((id)[0] & (1 << 7))
 #define ata_id_has_dword_io(id)        ((id)[50] & (1 << 0))
 #define ata_id_u32(id,n)       \
@@ -272,6 +295,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;
@@ -311,6 +336,15 @@ static inline int is_atapi_taskfile(const struct ata_taskfile *tf)
               (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))
index b80d2e7..c51502c 100644 (file)
@@ -33,6 +33,7 @@
 #include <asm/io.h>
 #include <linux/ata.h>
 #include <linux/workqueue.h>
+#include <scsi/scsi_host.h>
 
 /*
  * compile-time options: to be removed as soon as all the drivers are
@@ -44,7 +45,6 @@
 #undef ATA_NDEBUG              /* define to disable quick runtime checks */
 #undef ATA_ENABLE_PATA         /* define to enable PATA support in some
                                 * low-level drivers */
-#undef ATAPI_ENABLE_DMADIR     /* enables ATAPI DMADIR bridge support */
 
 
 /* note: prints function name for you */
@@ -108,8 +108,11 @@ 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           = 32,
+       ATA_TAG_INTERNAL        = ATA_MAX_QUEUE - 1,
        ATA_MAX_SECTORS         = 200,  /* FIXME */
+       ATA_MAX_SECTORS_LBA48   = 65535,
        ATA_MAX_BUS             = 2,
        ATA_DEF_BUSY_WAIT       = 10000,
        ATA_SHORT_PAUSE         = (HZ >> 6) + 1,
@@ -120,9 +123,13 @@ enum {
        ATA_SHT_USE_CLUSTERING  = 1,
 
        /* struct ata_device stuff */
-       ATA_DFLAG_LBA48         = (1 << 0), /* device supports LBA48 */
-       ATA_DFLAG_PIO           = (1 << 1), /* device currently in PIO mode */
-       ATA_DFLAG_LBA           = (1 << 2), /* device supports LBA */
+       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_NCQ           = (1 << 3), /* device supports NCQ */
+       ATA_DFLAG_CFG_MASK      = (1 << 8) - 1,
+
+       ATA_DFLAG_PIO           = (1 << 8), /* device currently in PIO mode */
 
        ATA_DEV_UNKNOWN         = 0,    /* unknown device */
        ATA_DEV_ATA             = 1,    /* ATA device */
@@ -132,43 +139,51 @@ enum {
        ATA_DEV_NONE            = 5,    /* no device */
 
        /* struct ata_port flags */
-       ATA_FLAG_SLAVE_POSS     = (1 << 1), /* host supports slave dev */
+       ATA_FLAG_SLAVE_POSS     = (1 << 0), /* host supports slave dev */
                                            /* (doesn't imply presence) */
-       ATA_FLAG_PORT_DISABLED  = (1 << 2), /* port is disabled, ignore it */
-       ATA_FLAG_SATA           = (1 << 3),
-       ATA_FLAG_NO_LEGACY      = (1 << 4), /* no legacy mode check */
-       ATA_FLAG_SRST           = (1 << 5), /* (obsolete) use ATA SRST, not E.D.D. */
-       ATA_FLAG_MMIO           = (1 << 6), /* use MMIO, not PIO */
-       ATA_FLAG_SATA_RESET     = (1 << 7), /* (obsolete) use COMRESET */
-       ATA_FLAG_PIO_DMA        = (1 << 8), /* PIO cmds via DMA */
-       ATA_FLAG_NOINTR         = (1 << 9), /* FIXME: Remove this once
-                                            * proper HSM is in place. */
-       ATA_FLAG_DEBUGMSG       = (1 << 10),
-       ATA_FLAG_NO_ATAPI       = (1 << 11), /* No ATAPI support */
-
-       ATA_FLAG_SUSPENDED      = (1 << 12), /* port is suspended */
-
-       ATA_FLAG_PIO_LBA48      = (1 << 13), /* Host DMA engine is LBA28 only */
-       ATA_FLAG_IRQ_MASK       = (1 << 14), /* Mask IRQ in PIO xfers */
-
-       ATA_FLAG_FLUSH_PORT_TASK = (1 << 15), /* Flush port task */
-       ATA_FLAG_IN_EH          = (1 << 16), /* EH in progress */
-
-       ATA_QCFLAG_ACTIVE       = (1 << 1), /* cmd not yet ack'd to scsi lyer */
-       ATA_QCFLAG_SG           = (1 << 3), /* have s/g table? */
-       ATA_QCFLAG_SINGLE       = (1 << 4), /* no s/g, just a single buffer */
+       ATA_FLAG_SATA           = (1 << 1),
+       ATA_FLAG_NO_LEGACY      = (1 << 2), /* no legacy mode check */
+       ATA_FLAG_MMIO           = (1 << 3), /* use MMIO, not PIO */
+       ATA_FLAG_SRST           = (1 << 4), /* (obsolete) use ATA SRST, not E.D.D. */
+       ATA_FLAG_SATA_RESET     = (1 << 5), /* (obsolete) use COMRESET */
+       ATA_FLAG_NO_ATAPI       = (1 << 6), /* No ATAPI support */
+       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_NCQ            = (1 << 11), /* host supports NCQ */
+
+       ATA_FLAG_DEBUGMSG       = (1 << 14),
+       ATA_FLAG_FLUSH_PORT_TASK = (1 << 15), /* flush port task */
+
+       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 */
+
+       /* struct ata_queued_cmd flags */
+       ATA_QCFLAG_ACTIVE       = (1 << 0), /* cmd not yet ack'd to scsi lyer */
+       ATA_QCFLAG_SG           = (1 << 1), /* have s/g table? */
+       ATA_QCFLAG_SINGLE       = (1 << 2), /* no s/g, just a single buffer */
        ATA_QCFLAG_DMAMAP       = ATA_QCFLAG_SG | ATA_QCFLAG_SINGLE,
-       ATA_QCFLAG_EH_SCHEDULED = (1 << 5), /* EH scheduled */
+       ATA_QCFLAG_IO           = (1 << 3), /* standard IO command */
+       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,
 
@@ -207,21 +222,44 @@ enum {
        /* size of buffer to pad xfers ending on unaligned boundaries */
        ATA_DMA_PAD_SZ          = 4,
        ATA_DMA_PAD_BUF_SZ      = ATA_DMA_PAD_SZ * ATA_MAX_QUEUE,
-       
-       /* Masks for port functions */
+
+       /* masks for port functions */
        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 {
@@ -245,7 +283,7 @@ struct ata_queued_cmd;
 /* typedefs */
 typedef void (*ata_qc_cb_t) (struct ata_queued_cmd *qc);
 typedef void (*ata_probeinit_fn_t)(struct ata_port *);
-typedef int (*ata_reset_fn_t)(struct ata_port *, int, unsigned int *);
+typedef int (*ata_reset_fn_t)(struct ata_port *, unsigned int *);
 typedef void (*ata_postreset_fn_t)(struct ata_port *ap, unsigned int *);
 
 struct ata_ioports {
@@ -336,7 +374,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;
@@ -348,12 +386,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;
@@ -373,6 +423,24 @@ struct ata_device {
        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 {
@@ -397,12 +465,21 @@ struct ata_port {
        unsigned int            mwdma_mask;
        unsigned int            udma_mask;
        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];
-       unsigned long           qactive;
+       unsigned long           qc_allocated;
+       unsigned int            qc_active;
+
        unsigned int            active_tag;
+       u32                     sactive;
 
        struct ata_host_stats   stats;
        struct ata_host_set     *host_set;
@@ -411,12 +488,13 @@ struct ata_port {
        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 {
@@ -450,7 +528,15 @@ 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 *);
@@ -496,18 +582,16 @@ extern void ata_port_probe(struct ata_port *);
 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 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,
                        ata_postreset_fn_t postreset, unsigned int *classes);
 extern void ata_std_probeinit(struct ata_port *ap);
-extern int ata_std_softreset(struct ata_port *ap, int verbose,
-                            unsigned int *classes);
-extern int sata_std_hardreset(struct ata_port *ap, int verbose,
-                             unsigned int *class);
+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
@@ -523,20 +607,27 @@ extern void ata_host_set_remove(struct ata_host_set *host_set);
 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,
                                   unsigned long timeout);
 extern void ata_port_queue_task(struct ata_port *ap, void (*fn)(void *),
                                void *data, unsigned long delay);
+extern u32 ata_wait_register(void __iomem *reg, u32 mask, u32 val,
+                            unsigned long interval_msec,
+                            unsigned long timeout_msec);
 
 /*
  * Default driver ops implementations
@@ -572,17 +663,26 @@ extern void ata_bmdma_start (struct ata_queued_cmd *qc);
 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_eng_timeout(struct ata_port *ap);
-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 int ata_qc_complete_multiple(struct ata_port *ap, u32 qc_active,
+                                   void (*finish_qc)(struct ata_queued_cmd *));
+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 int ata_scsi_change_queue_depth(struct scsi_device *sdev,
+                                      int queue_depth);
+extern struct ata_device *ata_dev_pair(struct ata_device *adev);
 
 /*
  * Timing helpers
@@ -628,7 +728,50 @@ extern int pci_test_config_bits(struct pci_dev *pdev, const struct pci_bits *bit
 extern unsigned long ata_pci_default_filter(const struct ata_port *, struct ata_device *, unsigned long);
 #endif /* CONFIG_PCI */
 
+/*
+ * 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)
 {
@@ -671,14 +814,39 @@ static inline unsigned int ata_tag_valid(unsigned int tag)
        return (tag < ATA_MAX_QUEUE) ? 1 : 0;
 }
 
-static inline unsigned int ata_class_present(unsigned int class)
+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;
 }
 
-static inline unsigned int ata_dev_present(const struct ata_device *dev)
+static inline unsigned int ata_class_disabled(unsigned int class)
+{
+       return class == ATA_DEV_ATA_UNSUP || class == ATA_DEV_ATAPI_UNSUP;
+}
+
+static inline unsigned int ata_class_absent(unsigned int class)
+{
+       return !ata_class_enabled(class) && !ata_class_disabled(class);
+}
+
+static inline unsigned int ata_dev_enabled(const struct ata_device *dev)
+{
+       return ata_class_enabled(dev->class);
+}
+
+static inline unsigned int ata_dev_disabled(const struct ata_device *dev)
+{
+       return ata_class_disabled(dev->class);
+}
+
+static inline unsigned int ata_dev_absent(const struct ata_device *dev)
 {
-       return ata_class_present(dev->class);
+       return ata_class_absent(dev->class);
 }
 
 static inline u8 ata_chk_status(struct ata_port *ap)
@@ -759,20 +927,35 @@ static inline void ata_qc_set_polling(struct ata_queued_cmd *qc)
        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;
@@ -787,26 +970,11 @@ static inline void ata_qc_reinit(struct ata_queued_cmd *qc)
        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;
 }
 
 /**
@@ -885,28 +1053,6 @@ static inline u8 ata_irq_ack(struct ata_port *ap, unsigned int chk_drq)
        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) ||
@@ -916,7 +1062,7 @@ static inline int ata_try_flush_cache(const struct ata_device *dev)
 
 static inline unsigned int ac_err_mask(u8 status)
 {
-       if (status & ATA_BUSY)
+       if (status & (ATA_BUSY | ATA_DRQ))
                return AC_ERR_HSM;
        if (status & (ATA_ERR | ATA_DF))
                return AC_ERR_DEV;
@@ -944,4 +1090,9 @@ static inline void ata_pad_free(struct ata_port *ap, struct device *dev)
        dma_free_coherent(dev, ATA_DMA_PAD_BUF_SZ, ap->pad, ap->pad_dma);
 }
 
+static inline struct ata_port *ata_shost_to_port(struct Scsi_Host *host)
+{
+       return (struct ata_port *) &host->hostdata[0];
+}
+
 #endif /* __LINUX_LIBATA_H__ */
index d6fe048..233f607 100644 (file)
 #define PCI_DEVICE_ID_NVIDIA_QUADRO_FX_1100         0x034E
 #define PCI_DEVICE_ID_NVIDIA_NVENET_14              0x0372
 #define PCI_DEVICE_ID_NVIDIA_NVENET_15              0x0373
+#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA      0x03E7
+#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_IDE       0x03EC
+#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA2     0x03F6
+#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA3     0x03F7
 
 #define PCI_VENDOR_ID_IMS              0x10e0
 #define PCI_DEVICE_ID_IMS_TT128                0x9128
index 1ace1b9..88c6c4d 100644 (file)
@@ -151,5 +151,6 @@ extern struct scsi_cmnd *scsi_get_command(struct scsi_device *, gfp_t);
 extern void scsi_put_command(struct scsi_cmnd *);
 extern void scsi_io_completion(struct scsi_cmnd *, unsigned int, unsigned int);
 extern void scsi_finish_command(struct scsi_cmnd *cmd);
+extern void scsi_req_abort_cmd(struct scsi_cmnd *cmd);
 
 #endif /* _SCSI_SCSI_CMND_H */
index de6ce54..a42efd6 100644 (file)
@@ -472,6 +472,7 @@ struct Scsi_Host {
         */
        unsigned int host_busy;            /* commands actually active on low-level */
        unsigned int host_failed;          /* commands that failed. */
+       unsigned int host_eh_scheduled;    /* EH scheduled without command */
     
        unsigned short host_no;  /* Used for IOCTL_GET_IDLUN, /proc/scsi et al. */
        int resetting; /* if set, it means that last_reset is a valid value */